Me gustaría entender la sintaxis del complemento jQuery

89

El sitio jQuery enumera la sintaxis básica del complemento para jQuery de la siguiente manera:

(function( $ ){    
  $.fn.myPlugin = function() {      
    // there's no need to do $(this) because
    // "this" is already a jquery object

    // $(this) would be the same as $($('#element'));

    this.fadeIn('normal', function(){    
      // the this keyword is a DOM element    
    });    
  };
})( jQuery );

Solo me gustaría entender lo que está sucediendo allí desde el punto de vista de Javascript, porque no parece que siga ninguna sintaxis que haya visto antes en JS. Así que aquí está mi lista de preguntas:

  1. Si reemplaza la función ($) ... con una variable, diga "the_function", la sintaxis se ve así:

     (the_function)( jQuery );

    ¿Qué es "(jQuery);" ¿haciendo? ¿Son realmente necesarios los paréntesis alrededor de la función? ¿Por qué están ellos ahí? ¿Hay otra pieza de código que pueda dar que sea similar?

  2. Comienza con la función ($). Entonces, ¿está creando una función, que hasta donde yo sé, nunca se ejecutará, con el parámetro de $, que ya está definido? ¿Que esta pasando ahí?

¡Gracias por la ayuda!

Ethan
fuente

Respuestas:

130
function(x){ 
    x...
}

es solo una función sin nombre, que toma un argumento, "x", y hace cosas con x.

En lugar de 'x', que es un nombre de variable común, puede usar $, que es un nombre de variable menos común, pero aún legal.

function($){ 
    $...
}

Lo pondré entre paréntesis para asegurarme de que se analiza como una expresión:

(function($){
    $....
})

Para llamar a una función, coloca () después de ella con una lista de argumentos. Por ejemplo, si quisiéramos llamar a esta función pasando 3 por el valor de $, haríamos esto:

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

Solo por diversión, llamemos a esta función y pasemos jQuery como una variable:

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

Esto crea una nueva función que toma un argumento y luego llama a esa función, pasando jQuery como valor.

¿POR QUÉ?

  • Porque escribir jQuery cada vez que quieres hacer algo con jQuery es tedioso.

¿POR QUÉ NO SÓLO ESCRIBIR $ = jQuery?

  • Porque alguien más podría haber definido $ para significar otra cosa. Esto garantiza que cualquier otro significado de $ quede ensombrecido por este.
Joel Spolsky
fuente
20
Está claro, pero falta una explicación detallada de la necesidad de guiar al analizador para que analice la definición de la función como una expresión y no como una declaración . Para eso son los paréntesis extra .
Puntiagudo
16
(function(){})()se conoce como IIFE (expresión de función invocada inmediatamente) . Que se sepa que puede utilizar otros símbolos para forzar al analizador para el tratamiento de la función como una expresión como +,!,-,~(y otros) así: !function($){}(jQuery). Y para divertirse aún más, puede ~~+-!function($){}(jQuery):!
David Murdoch
(función ($, win, doc) {$ ....}) (jQuery, ventana, documento); Yo también agregaría esto ... Me ayudó a entender mejor. en esta paz de código, jQuery ---> $; y ventana ---> ganar; luego documento ---> doc ... :) gracias ...
Haranadh
Me he enfrentado a una muestra de código que, en mi humilde opinión, no está cubierta en la lista anterior: $ (function () {.....} (jQuery)); (Tomado de aquí: docs.microsoft.com/en-us/aspnet/core/mvc/models/… ). Aquí, no entiendo el uso de $. No parece ser un selector de jQuery $ (...) o una sintaxis corta para el evento 'documento listo', porque la función no devuelve nada. Tampoco parece ser un prefijo para tratar la función como una expresión, porque está fuera de las llaves. Además, la llamada a la función se realiza DENTRO de las llaves, por lo que estamos llamando a declaración.
sich
35

(function( $ ){

})( jQuery );

Esa es una función anónima autoejecutable que se usa $en un argumento para que pueda usarla ( $) en lugar de jQuerydentro de esa función y sin temor a entrar en conflicto con otras bibliotecas porque en otras bibliotecas también $tiene un significado especial. Ese patrón es especialmente útil al escribir complementos de jQuery.

Puede escribir cualquier carácter allí en lugar de $también:

(function(j){
  // can do something like 
  j.fn.function_name = function(x){};

})(jQuery);

Aquí se jpondrá al día automáticamente con jQuery especificado al final (jQuery). O puede omitir el argumento por completo, pero luego tendrá que usar jQuerypalabras clave en todas partes en lugar de $sin temor a una colisión todavía. Por $lo tanto, está envuelto en el argumento de la abreviatura para que pueda escribir en $lugar de jQuerytodo dentro de esa función.

Si incluso mira el código fuente de jQuery, verá que todo está envuelto en el medio:

(function( window, undefined ) {
  // jQuery code
})(window);

Eso es como puede verse también una función anónima autoejecutable con argumentos. Se crea un argumento window(y undefined) y se asigna con el windowobjeto global en la parte inferior (window). Este es un patrón popular en estos días y tiene poca ganancia de velocidad porque aquí windowse analizará desde el argumento en lugar del windowobjeto global que se asigna a continuación.


El $.fnes objeto de jQuery donde se crea su nueva función (que es también un objeto) o el propio plugin jQuery para que envuelve su plugin en su $.fnobjeto y ponerlo a disposición.


Curiosamente, había respondido una pregunta similar aquí:

Sintaxis de la función de cierre de JavaScript / jQuery

También puede consultar este artículo para saber más sobre las funciones autoejecutables que había escrito:

Funciones autoejecutables de JavaScript

Sarfraz
fuente
Entonces, si tuviera un objeto llamado my_object, e hiciera esto: (function (mo) {mo.doSomething ()}) (my_object), entonces ejecutaría my_object.doSomething ()?
Ethan
3

La sintaxis básica del complemento le permite usar $una referencia jQueryen el cuerpo de su complemento, independientemente de la identidad $en el momento en que se carga el complemento. Esto evita conflictos de nombres con otras bibliotecas, especialmente Prototype.

La sintaxis define una función que acepta un parámetro conocido como $para que pueda referirse a él como $en el cuerpo de la función, y luego inmediatamente invoca esa función, poniéndola jQuerycomo argumento.

Esto también ayuda a no contaminar el espacio de nombres global (por lo que declarar var myvar = 123;en el cuerpo de su complemento no se definirá repentinamente window.myvar), pero el principal propósito ostensible es permitirle usar $donde $puede haber sido redefinido desde entonces.

Steven
fuente
3

Se trata de una función anónima que se autoinvoca allí. Es como una "mejor práctica" envolver un complemento de jQuery dentro de dicha función para asegurarse de que el $letrero esté vinculado al jQueryobjeto.

Ejemplo:

(function(foo) {
    alert(foo);
}('BAR'));

Esto alertaría BARcuando se coloque en un <script>bloque. El parámetro BARse pasa a la función que se llama a sí misma.

El mismo principio está sucediendo en su código, el jQueryobjeto se pasa a la función, por lo que $se referirá al objeto jQuery con seguridad.

jAndy
fuente
1
Entiendo todo eso. Lo que quiero saber es por qué / cómo funciona la sintaxis de corchetes para crear una función autoejecutable. ¿Es eso solo una característica del idioma? ¿Como funciona?
carne
2

El jQuery al final se pasa a sí mismo (jQuery) a la función, para que pueda usar el símbolo $ dentro de su complemento. Tú también podrías hacer

(function(foo){

  foo.fn.myPlugin = function() {


    this.fadeIn('normal', function(){


    });

  };
})( jQuery );
arpax
fuente
2

Para encontrar una explicación clara de este y otros trucos modernos de JavaScript y prácticas comunes, recomiendo leer Javascript Garden.

http://bonsaiden.github.com/JavaScript-Garden/

Es especialmente útil, porque muchos de estos patrones se usan ampliamente en muchas bibliotecas pero no se explican realmente.

OlliM
fuente
2

Las otras respuestas aquí son excelentes, pero hay un punto importante que no se ha abordado. Tu dices:

Entonces, ¿está creando una función, que hasta donde yo sé, nunca se ejecutará, con el parámetro de $, que ya está definido?

No hay garantía de que la variable global $esté disponible . De forma predeterminada, jQuery crea dos variables en el alcance global: $y jQuery(donde los dos son alias para el mismo objeto). Sin embargo, jQuery también se puede ejecutar en modo noConflict :

<script type="text/javascript" src="jquery.js"></script>
<script type="text/javascript">
  jQuery.noConflict();
</script>

Cuando llama jQuery.noConflict(), la variable global $se vuelve a establecer en lo que era antes de que se incluyera la biblioteca jQuery. Esto permite que jQuery se utilice con otras bibliotecas de Javascript que también se utilizan $como variable global.

Si escribió un complemento que se basaba en $ser un alias para jQuery, entonces su complemento no funcionaría para los usuarios que se ejecutan en modo noConflict.

Como ya han explicado otros, el código que publicó crea una función anónima a la que se llama inmediatamente. jQueryLuego, la variable global se pasa a esta función anónima, que tiene un alias seguro como la variable local$ dentro de la función.

Dormir
fuente