Estaba leyendo algunas publicaciones sobre cierres y vi esto en todas partes, pero no hay una explicación clara de cómo funciona, cada vez que me dijeron que lo usara ...:
// Create a new anonymous function, to use as a wrapper
(function(){
// The variable that would, normally, be global
var msg = "Thanks for visiting!";
// Binding a new function to a global object
window.onunload = function(){
// Which uses the 'hidden' variable
alert( msg );
};
// Close off the anonymous function and execute it
})();
Ok, veo que crearemos una nueva función anónima y luego la ejecutaremos. Entonces, después de eso, este código simple debería funcionar (y lo hace):
(function (msg){alert(msg)})('SO');
Mi pregunta es ¿qué tipo de magia sucede aquí? Pensé que cuando escribí:
(function (msg){alert(msg)})
entonces se crearía una nueva función sin nombre como la función "" (msg) ...
pero entonces ¿por qué esto no funciona?
(function (msg){alert(msg)});
('SO');
¿Por qué necesita estar en la misma línea?
¿Podrías señalarme algunas publicaciones o darme una explicación?
(function (msg){alert(msg)})('SO');
funciona completamente por sí sola. No tiene nada que ver con la otra función anónima que publicó antes. Esas son dos funciones anónimas completamente separadas. Debe invocar una función anónima de inmediato porque no tiene nombre y no se puede hacer referencia después.Respuestas:
Suelte el punto y coma después de la definición de la función.
Arriba debería funcionar.
Página DEMO: https://jsfiddle.net/e7ooeq6m/
He discutido este tipo de patrón en esta publicación:
jQuery y $ preguntas
EDITAR:
Si observa la especificación del script ECMA , hay 3 formas en que puede definir una función. (Página 98, Sección 13 Definición de funciones)
1. Usando el constructor de funciones
2. Uso de la declaración de función.
3. Expresión de funciones
Entonces puede preguntar, ¿cuál es la diferencia entre declaración y expresión?
De la especificación del script ECMA:
Si observa, 'identificador' es opcional para la expresión de la función. Y cuando no proporciona un identificador, crea una función anónima. No significa que no pueda especificar un identificador.
Esto significa que lo siguiente es válido.
Un punto importante a tener en cuenta es que puede usar 'mySum' solo dentro del cuerpo de la función mySum, no afuera. Ver el siguiente ejemplo:
Demo en vivo
Compara esto con
Armados con este conocimiento, intentemos analizar su código.
Cuando tienes un código como,
Creaste una expresión de función. Y puede ejecutar esta expresión de función envolviéndola entre paréntesis.
fuente
Se llama una función auto invocada.
Lo que está haciendo cuando llama
(function(){})
es devolver un objeto de función. Cuando lo anexas()
, se invoca y se ejecuta cualquier cosa en el cuerpo. El;
denota el final de la instrucción, es por eso que no pasa la segunda invocación.fuente
Una cosa que encontré confusa es que los "()" son operadores de agrupación.
Aquí está su función básica declarada.
Ex. 1:
Las funciones son objetos y se pueden agrupar. Así que echemos parens alrededor de la función.
Ex. 2:
Ahora, en lugar de declarar y llamar de inmediato a la misma función, podemos usar la sustitución básica para declararla como la llamamos.
Ex. 3)
Finalmente, no tenemos necesidad de ese foo extra porque no estamos usando el nombre para llamarlo. Las funciones pueden ser anónimas.
Ex. 4)
Para responder a su pregunta, consulte el Ejemplo 2. Su primera línea declara alguna función sin nombre y la agrupa, pero no la llama. La segunda línea agrupa una cadena. Ambos no hacen nada. (El primer ejemplo de Vincent).
Pero
fuente
Una función anónima no es una función con el nombre "". Es simplemente una función sin nombre.
Al igual que cualquier otro valor en JavaScript, una función no necesita un nombre para crearse. Aunque es mucho más útil vincularlo a un nombre como cualquier otro valor.
Pero como cualquier otro valor, a veces desea usarlo sin vincularlo a un nombre. Ese es el patrón de auto-invocación.
Aquí hay una función y un número, no vinculados, no hacen nada y nunca se pueden usar:
Entonces tenemos que almacenarlos en una variable para poder usarlos, como cualquier otro valor:
También puede usar azúcar sintáctico para unir la función a una variable:
Pero si no es necesario nombrarlos y generaría más confusión y menos legibilidad, puede usarlos de inmediato.
Aquí, mi función y mis números no están vinculados a una variable, pero aún pueden usarse.
Dicho así, parece que la función de invocación automática no tiene ningún valor real. Pero debe tener en cuenta que el delimitador de alcance de JavaScript es la función y no el bloque ({}).
Por lo tanto, una función de invocación automática tiene el mismo significado que un bloque C ++, C # o Java. Lo que significa que la variable creada dentro no se "escapará" fuera del alcance. Esto es muy útil en JavaScript para no contaminar el alcance global.
fuente
Así es como funciona JavaScript. Puede declarar una función con nombre:
Y llámalo:
O puede declarar una función anónima:
Y llama eso:
O bien, nunca puedes vincular la función a un nombre:
Las funciones también pueden devolver funciones:
No vale nada que cualquier variable definida con "var" en el cuerpo de
make_foo
sea cerrada por cada función devuelta pormake_foo
. Esto es un cierre, y significa que cualquier cambio realizado en el valor por una función será visible por otra.Esto le permite encapsular información, si lo desea:
Es casi lo que funciona cada lenguaje de programación, excepto Java.
fuente
El código que muestra,
consisten en dos declaraciones. La primera es una expresión que produce un objeto de función (que luego se recolectará como basura porque no se guarda). La segunda es una expresión que produce una cadena. Para aplicar la función a la cadena, debe pasar la cadena como argumento a la función cuando se crea (que también se muestra arriba), o deberá almacenar la función en una variable, para que pueda aplíquelo en otro momento, a su gusto. Al igual que:
Tenga en cuenta que al almacenar una función anónima (una función lambda) en una variable, efectivamente le está dando un nombre. Por lo tanto, puede definir una función regular:
fuente
En resumen de los comentarios anteriores:
cuando no se asigna a una variable, produce un error de sintaxis. El código se analiza como una declaración de función (o definición), que hace que los paréntesis de cierre sean sintácticamente incorrectos. Agregar paréntesis alrededor de la parte de la función le dice al intérprete (y al programador) que esta es una expresión de función (o invocación), como en
Esta es una función de invocación automática, lo que significa que se crea de forma anónima y se ejecuta de inmediato porque la invocación ocurre en la misma línea donde se declara. Esta función de auto-invocación se indica con la sintaxis familiar para llamar a una función sin argumentos, además de paréntesis, agregó alrededor del nombre de la función:
(myFunction)();
.Hay una buena sintaxis de la función JavaScript de discusión SO .
fuente
Esta respuesta no está estrictamente relacionada con la pregunta, pero es posible que le interese descubrir que este tipo de característica de sintaxis no es específica de las funciones. Por ejemplo, siempre podemos hacer algo como esto:
Relacionado con las funciones. Como son objetos, que heredan de Function.prototype, podemos hacer cosas como:
Y ya sabes, ni siquiera tenemos que rodear las funciones con paréntesis para ejecutarlas. De todos modos, siempre que tratemos de asignar el resultado a una variable.
Otra cosa que puede hacer con las funciones, tan pronto como las declare, es invocar al
new
operador sobre ellas y obtener un objeto. Los siguientes son equivalentes:fuente
Hay una propiedad más que tiene la función JavaScript. Si desea llamar a la misma función anónima de forma recursiva.
fuente
Mi comprensión de la pregunta del autor de la pregunta es tal que:
¿Cómo funciona esta magia?
Puedo estar equivocado. Sin embargo, la práctica habitual con la que las personas están familiarizadas es:
La razón es que JavaScript paréntesis AKA
()
, no puede contener declaraciones y cuando el analizador encuentra la palabra clave de función, sabe analizarla como una expresión de función y no como una declaración de función.Fuente: publicación de blog Expresión de función invocada inmediatamente (IIFE)
fuente
ejemplos sin corchetes:
(este es el único uso real de void, afaik)
o
o
funciona igual de bien la
void
está causando la expresión para evaluar, así como la asignación y la explosión. el último que trabaja con~
,+
,-
,delete
,typeof
, algunos de los operadores unitarios (void
es uno también). no funcionan son de hecho++
,--
debido al requisito de una variable.El salto de línea no es necesario.
fuente
delete
funciona. incluso con'use strict';
. esto también funciona:delete (3 + 4);
Es una función anónima de ejecución automática. El primer conjunto de corchetes contiene las expresiones que se ejecutarán, y el segundo conjunto de corchetes ejecuta esas expresiones.
Peter Michaux discute la diferencia en un par importante de paréntesis .
Es una construcción útil cuando se intenta ocultar variables del espacio de nombres principal. Todo el código dentro de la función está contenido en el ámbito privado de la función, lo que significa que no se puede acceder a él desde fuera de la función, por lo que es verdaderamente privado.
Ver:
fuente
Otro punto de vista
Primero, puede declarar una función anónima:
Entonces lo llamas:
Porque foo = function (msg) {alert (msg);} por lo que puede reemplazar foo como:
Pero debe envolver toda su función anónima dentro de un par de llaves para evitar el error de sintaxis de declarar la función al analizar. Entonces nosotros tenemos,
De esta manera, es fácil de entender para mí.
fuente
Cuando lo hiciste:
Terminó la función antes
('SO')
debido al punto y coma. Si solo escribes:Funcionará.
Ejemplo de trabajo: http://jsfiddle.net/oliverni/dbVjg/
fuente
La razón simple por la que no funciona no se debe a que
;
indica el final de la función anónima. Es porque sin el()
fin de una llamada a la función, no es una llamada a la función. Es decir,Si llama,
result = help();
es una llamada a una función y devolverá verdadero.Si llamas
result = help;
esto no es una llamada. Es una tarea en la que la ayuda se trata como datos que se asignarán al resultado.Lo que hiciste fue declarar / instanciar una función anónima agregando el punto y coma,
y luego traté de llamarlo en otra declaración usando solo paréntesis ... Obviamente porque la función no tiene nombre, pero esto no funcionará:
El intérprete ve los paréntesis en la segunda línea como una nueva instrucción / declaración, y por lo tanto no funciona, incluso si lo hizo así:
Todavía no funciona, pero funciona cuando elimina el punto y coma porque el intérprete ignora los espacios en blanco y los carruajes y ve el código completo como una declaración.
Conclusión: una llamada a la función no es una llamada a la función sin el
()
fin a menos que bajo condiciones específicas, como ser invocado por otra función, es decir, onload = 'help' ejecutaría la función de ayuda aunque los paréntesis no estuvieran incluidos. Creo que setTimeout y setInterval también permiten este tipo de llamadas a funciones, y también creo que el intérprete agrega los paréntesis detrás de escena de todos modos, lo que nos lleva nuevamente a "una llamada a funciones no es una llamada a funciones sin paréntesis".fuente
Este es un método común para usar una función anónima como cierre que utilizan muchos marcos JavaScript.
Esta función llamada es automática cuando se compila el código.
Si coloca
;
en la primera línea, el compilador lo trata como dos líneas diferentes. Por lo tanto, no puede obtener los mismos resultados que anteriormente.Esto también se puede escribir como:
Para obtener más detalles, consulte JavaScript / Funciones anónimas .
fuente
Las funciones anónimas son funciones que se declaran dinámicamente en tiempo de ejecución. Se llaman funciones anónimas porque no se les da un nombre de la misma manera que las funciones normales.
Las funciones anónimas se declaran utilizando el operador de función en lugar de la declaración de función. Puede usar el operador de función para crear una nueva función siempre que sea válida para poner una expresión. Por ejemplo, podría declarar una nueva función como parámetro para una llamada de función o asignar una propiedad de otro objeto.
Aquí hay un ejemplo típico de una función con nombre:
función flyToTheMoon () {alert ("¡Zoom! ¡Zoom! ¡Zoom!"); } volar a la luna(); Aquí está el mismo ejemplo creado como una función anónima:
var flyToTheMoon = function () {alert ("¡Zoom! ¡Zoom! ¡Zoom!"); } volar a la luna();
Para más detalles, lea aquí:
http://helephant.com/2008/08/23/javascript-anonymous-functions/
fuente
El IIFE simplemente compartimenta la función y oculta la
msg
variable para no "contaminar" el espacio de nombres global. En realidad, manténgalo simple y haga lo siguiente a menos que esté creando un sitio web de mil millones de dólares.Puede asignar un espacio de nombre a su
msg
propiedad utilizando un patrón de módulo revelador como:fuente
Las funciones anónimas están destinadas a ser una operación única en la que define una función sobre la marcha para que genere una salida de usted a partir de una entrada que está proporcionando. Excepto que no proporcionó la entrada. En cambio, escribiste algo en la segunda línea ('SO'); - una declaración independiente que no tiene nada que ver con la función. ¿Que esperabas? :)
fuente
var foo = function() {};
. Sin embargo, todo lo demás está bien.