¿Cuál es el propósito de pasar argumentos a funciones anónimas de esta manera? [duplicate]

4 minutos de lectura

avatar de usuario
kyle macey

Posible duplicado:

¿Cómo funcionan los cierres de JavaScript?

estaba jugando con el Compilador de cierre de Googleponiendo un código aleatorio para ver qué haría.

Reescribió una de mis funciones para que se pareciera a esto:

(function(msg) { console.log(msg); })("Hello World!");​​​​​​​

donde parece que "Hello World" es el argumento pasado como msg a la función anónima que le precede. Lo estuve mirando por un momento y pensé que había visto algo similar en los complementos de jQuery que se parecen a:

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

Lo que ahora tiene más sentido para mí, en el ámbito de los conflictos con $. Pero, ¿cuál es la razón principal o el propósito de pasar argumentos a una función anónima como esta? ¿Por qué no definiría simplemente los argumentos como variables dentro de la función? ¿Hay alguna ventaja de rendimiento o flexibilidad para escribir funciones como esta?

  • Para ese código específico, no hay una razón real. Podrías simplemente hacer console.log("hello");. Pero generalmente es para crear algunas variables locales que solo son accesibles para algunas funciones que se crean dentro y se exportan.

    – Odio a los perezosos

    2 oct 2012 a las 21:29

  • Tendría curiosidad por ver su código original que resultó en ese formulario. Apuesto a que si tuviera ADVANCED_OPTIMIZATIONS habilitado, se desharía de la función por completo.

    – Odio a los perezosos

    2 oct 2012 a las 21:30

  • @ user1689607 la función era un poco diferente y mucho más larga. Lo hice breve para hacerlo limpio en SO. Más preguntas sobre el concepto que este ejemplo específico

    – Kyle Macey

    2 oct 2012 a las 21:32


  • Oh, si la pregunta es principalmente parámetros de función versus variables, ciertamente no es un problema de rendimiento. Es más probable que sea solo que podría evitar el var caracteres para reducir el tamaño del archivo.

    – Odio a los perezosos

    2 oct 2012 a las 21:34

  • Si pasa una variable global así, podrá cambiar su nombre mientras minimiza. Minificar no cambia el nombre de las variables globales, por lo que tener algo como ‘MyGlobalVariable.property’ ocupará mucho espacio si tiene 100 ocurrencias. Si lo pasa a su función anon y lo nombra igual por dentro, minifier cambiará su nombre a, por ejemplo a reduciendo el tamaño total de su aplicación.

    –Mike Grabowski

    11/11/2014 a las 20:32

Hay una diferencia significativa relacionada también con el alcance. El siguiente código:

(function(msg) { console.log(msg); })("Hello World!");​​​​​​​

es, en algunas circunstancias, más limpio en términos de contaminación del espacio de nombres que esto:

var msg = "Hello World!";
console.log(msg);

porque el segundo código deja una variable después de que ya no se necesita, pero puede interferir con otras partes del código.

Esto es especialmente importante cuando ejecuta el código mencionado fuera de cualquier otra función: en tal caso msg La variable estaría disponible en todas partes de la página, como variable global.

  • Pero, ¿cómo sería diferente de simplemente envolver su segundo ejemplo en una función anónima? la variable aún moriría al final

    – Kyle Macey

    2 oct 2012 a las 21:29

  • Tenía la impresión de que se refería a algo más como esto: jsfiddle.net/cv5Jp

    – Kevin B.

    2 oct 2012 a las 21:30

  • @KevinB Correcto, ¿cuál es la diferencia entre tu violín y la función que publiqué?

    – Kyle Macey

    2 oct 2012 a las 21:33


  • @ʎǝɔɐɯǝlʎʞ: El argumento sigue siendo válido en mi opinión. El compilador acaba de elegir (function(msg){ console.log(msg); })("sth") en vez de !function(msg){ console.log(msg); }("sth"), (function(){ var msg="sth"; console.log(msg); })() etc. Este es un ejemplo muy simple y no esperaría magia detrás de él, es solo uno de los métodos para hacerlo.

    – Tadeck

    2 oct 2012 a las 21:33

  • @ʎǝɔɐɯǝlʎʞ: Ok, ahora es obvio. Eso es sobre guardar variables innecesarias en el espacio de nombres global: primero está definiendo b() luego la usa una vez y permanece en el espacio de nombres global. Por lo tanto, la forma natural era cambiar la función en cualquier función autodenominada. Agregar un nuevo argumento en el cuerpo podría generar problemas con su código, la compilación no fue tan invasiva.

    – Tadeck

    2 oct 2012 a las 21:48

Básicamente, siempre es una buena idea mantener tu código envuelto en esto: (function(){/*code*/}()); para evitar que tus vars colisionen con las vars de otras personas.

Creo que lo principal a lo que se dirige el compilador de cierre es guardar los 5 caracteres:var  y =.

Depende un poco del contexto. Hay algunas condiciones en las que el compilador no intentará insertar ninguna función en absoluto (si la función de alcance contiene “eval”, por ejemplo). Si se trata de un alcance global y está ejecutando en modo AVANZADO, es simplemente que la oportunidad de inserción apareció después de que el compilador dejó de intentar funciones en línea (o hay un error en el código de inserción y perdió la oportunidad). Si ejecuta su salida de muestra a través del compilador en modo AVANZADO, obtiene esto:

console.log("Hello World!");

¿Ha sido útil esta solución?