Qué hace (function ($) {}) (jQuery); ¿media?

299

Estoy comenzando a escribir complementos de jQuery. Escribí tres pequeños complementos, pero simplemente he copiado la línea en todos mis complementos sin saber realmente lo que significa. ¿Alguien puede contarme un poco más sobre esto? Tal vez una explicación sea útil algún día al escribir un marco :)

¿Qué hace esto? (Sé que extiende jQuery de alguna manera, pero ¿hay algo más interesante que saber sobre esto?)

(function($) {

})(jQuery);

¿Cuál es la diferencia entre las siguientes dos formas de escribir un complemento?

Tipo 1:

(function($) {
    $.fn.jPluginName = {

        },

        $.fn.jPluginName.defaults = {

        }
})(jQuery);

Tipo 2:

(function($) {
    $.jPluginName = {

        }
})(jQuery);

Tipo 3:

(function($){

    //Attach this new method to jQuery
    $.fn.extend({ 

        var defaults = {  
        }  

        var options =  $.extend(defaults, options);  

        //This is where you write your plugin's name
        pluginname: function() {

            //Iterate over the current set of matched elements
            return this.each(function() {

                //code to be inserted here

            });
        }
    }); 
})(jQuery);

Podría estar muy lejos aquí y tal vez todos significan lo mismo. Estoy confundido. En algunos casos, esto no parece estar funcionando en un complemento que estaba escribiendo usando el Tipo 1. Hasta ahora, el Tipo 3 me parece el más elegante, pero también me gustaría saber sobre los demás.

Leyenda
fuente
22
Es hora de acostarse aquí, pero solo para empezar, (function($) { })(jQuery);envuelve el código para que $esté jQuerydentro de ese cierre, incluso si $significa algo más fuera de él, generalmente como resultado de, $.noConflict()por ejemplo. Esto garantiza que su complemento funcione, independientemente de si $ === jQuery :)
Nick Craver
3
Sobre (function($) { })(jQuery)usted dijo: "Sé que extiende jQuery de alguna manera [...]". Claramente no lo sabe, ya que su declaración es 100% falsa. Por cierto, puede ser engañoso para futuros lectores. Eche un vistazo a esto: stackoverflow.com/a/32550649/1636522 .
hoja
Ampliando los comentarios de @ NickCraver, jquery-ui-1.7.2.custom.min.js utiliza esto, por ejemplo: jQuery.ui || (function (c) {var i = c.fn.remove, d = c.browser. mozilla ........}) (jQuery) ;. Sé que es una versión antigua de jQuery UI con código obsoleto, pero el punto es mostrar cómo en ese caso, están usando "c" en lugar de "$".
Jaime Montoya

Respuestas:

234

En primer lugar, un bloque de código que se parece (function(){})()es simplemente una función que se ejecuta en su lugar. Vamos a desglosarlo un poco.

1. (
2.    function(){}
3. )
4. ()

La línea 2 es una función simple, envuelta entre paréntesis para indicar al tiempo de ejecución que devuelva la función al ámbito principal, una vez que se devuelve la función se ejecuta utilizando la línea 4, tal vez leer estos pasos ayudará

1. function(){ .. }
2. (1)
3. 2()

Puede ver que 1 es la declaración, 2 está devolviendo la función y 3 solo está ejecutando la función.

Un ejemplo de cómo se usaría.

(function(doc){

   doc.location = '/';

})(document);//This is passed into the function above

En cuanto a las otras preguntas sobre los complementos:

Tipo 1: esto no es realmente un complemento, es un objeto pasado como una función, ya que los complementos tienden a ser funciones.

Tipo 2: nuevamente no es un complemento ya que no extiende el $.fnobjeto. Es solo una extensión del núcleo de jQuery, aunque el resultado es el mismo. Esto es si desea agregar funciones de desplazamiento como toArray, etc.

Tipo 3: este es el mejor método para agregar un complemento, el prototipo extendido de jQuery toma un objeto que contiene el nombre y la función del complemento y lo agrega a la biblioteca de complementos para usted.

RobertPitt
fuente
2
si lees la pregunta original, el OP especifica 3 métodos para escribir cierres, nombró a esos métodos tipo {1,2,3}, me refiero a las áreas dentro de la pregunta con una respuesta ..
RobertPitt
1
(function () {}) significa que devuelve la función interna? ¿Qué significa exactamente el "()"?
Jaskey
Me gusta el primer ejemplo, pero el segundo que usa referencias de número de línea (que no es una función js) no está claro.
Samy Bencherif
1
Eso se llama Expresión de función invocada inmediatamente (IIFE): benalman.com/news/2010/11/…
Andres Rojas
1
Tengo la mayoría de los problemas para comprender el paréntesis externo de ( function(){} ): ¿Qué es esto exactamente? ¿No puedo simplemente escribir function(){}()?
TMOTTM
127

En el nivel más básico, algo de la forma (function(){...})()es una función literal que se ejecuta inmediatamente. Lo que esto significa es que ha definido una función y la está llamando de inmediato.

Este formulario es útil para ocultar información y encapsular, ya que todo lo que defina dentro de esa función permanece local e inaccesible desde el mundo exterior (a menos que lo exponga específicamente, generalmente a través de un objeto literal devuelto).

Una variación de esta forma básica es lo que ve en los complementos de jQuery (o en este patrón de módulo en general). Por lo tanto:

(function($) {
  ...
})(jQuery);

Lo que significa que está pasando una referencia al jQueryobjeto real , pero se conoce como $dentro del alcance de la función literal.

El tipo 1 no es realmente un complemento. Simplemente está asignando un objeto literal a jQuery.fn. Por lo general, asigna una función, jQuery.fnya que los complementos generalmente son solo funciones.

El tipo 2 es similar al tipo 1; realmente no estás creando un complemento aquí. Simplemente está agregando un objeto literal a jQuery.fn.

Tipo 3 es un complemento, pero no es la mejor ni la más fácil forma de crear uno.

Para comprender más sobre esto, eche un vistazo a esta pregunta y respuesta similares . Además, esta página entra en detalles sobre la creación de complementos.

Vivin Paliath
fuente
1
No estoy seguro de cómo el Tipo 3 está extendiendo el núcleo. Es una forma perfectamente válida de crear un complemento ya que está extendiendo el prototipo. Aunque un poco innecesario.
tbranyen
1
Lo malo, debería haber sido más claro. Tenía prisa y tienes razón.
Vivin Paliath
32

Un poco de ayuda:

// an anonymous function
  
(function () { console.log('allo') });

// a self invoked anonymous function

(function () { console.log('allo') })();
  
// a self invoked anonymous function with a parameter called "$"
  
var jQuery = 'I\'m not jQuery.';

(function ($) { console.log($) })(jQuery);

hoja
fuente
21

Solo una pequeña adición a la explicación

Esta estructura (function() {})();se llama IIFE (Expresión de función invocada inmediatamente), se ejecutará inmediatamente, cuando el intérprete llegue a esta línea. Entonces, cuando estás escribiendo estas filas:

(function($) {
  // do something
})(jQuery);

Esto significa que el intérprete invocará la función inmediatamente y pasará jQuerycomo un parámetro, que se utilizará dentro de la función como $.

Suicidio comercial
fuente
12

En realidad, este ejemplo me ayudó a entender lo que (function($) {})(jQuery);significa.

Considera esto:

// Clousure declaration (aka anonymous function)
var f = function(x) { return x*x; };
// And use of it
console.log( f(2) ); // Gives: 4

// An inline version (immediately invoked)
console.log( (function(x) { return x*x; })(2) ); // Gives: 4

Y ahora considera esto:

  • jQuery es una variable que contiene el objeto jQuery.
  • $es un nombre de variable como cualquier otro ( a, $b, a$betc.) y no tiene ningún significado especial, como en PHP.

Sabiendo que podemos echar otro vistazo a nuestro ejemplo:

var $f = function($) { return $*$; };
var jQuery = 2;
console.log( $f(jQuery) ); // Gives: 4

// An inline version (immediately invoked)
console.log( (function($) { return $*$; })(jQuery) ); // Gives: 4
Krzysztof Przygoda
fuente
Para mí, esta es la mejor respuesta. claro y tan simple
Saleh
11

Tipo 3, para que funcione tendría que verse así:

(function($){
    //Attach this new method to jQuery
    $.fn.extend({     
        //This is where you write your plugin's name
        'pluginname': function(_options) {
            // Put defaults inline, no need for another variable...
            var options =  $.extend({
                'defaults': "go here..."
            }, _options);

            //Iterate over the current set of matched elements
            return this.each(function() {

                //code to be inserted here

            });
        }
    }); 
})(jQuery);

No estoy seguro de por qué alguien usaría extender solo establecer directamente la propiedad en el prototipo jQuery, está haciendo exactamente lo mismo solo en más operaciones y más desorden.

tbranyen
fuente