javascript - tipos - ¿Por qué necesita invocar una función anónima en la misma línea?
pasar parametros a una funcion javascript desde html (19)
Las funciones anónimas son funciones que se declaran dinámicamente en tiempo de ejecución. Se llaman funciones anónimas porque no reciben 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 donde sea válido para poner una expresión. Por ejemplo, podría declarar una nueva función como un parámetro para una llamada de función o para asignar una propiedad de otro objeto.
Aquí hay un ejemplo típico de una función nombrada:
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 por favor lea aquí:
http://helephant.com/2008/08/23/javascript-anonymous-functions/
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 ocurre aquí? Pensé que cuando escribí:
(function (msg){alert(msg)})
entonces una nueva función sin nombre se crearía como la función "" (msg) ...
Pero entonces, ¿por qué no funciona esto?
(function (msg){alert(msg)});
(''SO'');
¿Por qué tiene que estar en la misma línea?
¿Podría por favor señalarme algunos mensajes o darme una explicación?
Así es como funciona JavaScript. Puedes declarar una función nombrada:
function foo(msg){
alert(msg);
}
Y llámalo:
foo("Hi!");
O bien, puede declarar una función anónima:
var foo = function (msg) {
alert(msg);
}
Y llama a eso:
foo("Hi!");
O, simplemente nunca puedes vincular la función a un nombre:
(function(msg){
alert(msg);
})("Hi!");
Las funciones también pueden devolver funciones:
function make_foo() {
return function(msg){ alert(msg) };
}
(make_foo())("Hi!");
No vale la pena que las variables definidas con "var" en el cuerpo de make_foo
sean cerradas por cada función devuelta por make_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:
function make_greeter(msg){
return function() { alert(msg) };
}
var hello = make_greeter("Hello!");
hello();
Es así como funciona casi todos los lenguajes de programación menos Java.
Cuando hiciste
(function (msg){alert(msg)});
(''SO'');
Terminaste la función antes (''SO'')
debido al punto y coma. Si solo escribes:
(function (msg){alert(msg)})
(''SO'');
Funcionará.
Ejemplo de trabajo: http://jsfiddle.net/oliverni/dbVjg/
Ejemplos sin corchetes:
void function (msg) { alert(msg); }
(''SO'');
(Este es el único uso real de void, afaik)
o
var a = function (msg) { alert(msg); }
(''SO'');
o
!function (msg) { alert(msg); }
(''SO'');
trabajar tambien el void
está haciendo que la expresión se evalúe, así como la asignación y la explosión. el último funciona con ~
, +
, -
, delete
, typeof
, algunos de los operadores únicos (el void
es uno). no funcionan son de couse ++
, --
debido al requisito de una variable.
El salto de línea no es necesario.
El IIFE simplemente divide la función y oculta la variable msg
para no "contaminar" el espacio de nombres global. En realidad, solo manténgalo simple y haga lo siguiente a menos que esté creando un sitio web de mil millones de dólares.
var msg = "later dude";
window.onunload = function(msg){
alert( msg );
};
Puede poner un espacio de nombre a su propiedad msg
usando un patrón de módulo revelador como:
var myScript = (function() {
var pub = {};
//myscript.msg
pub.msg = "later dude";
window.onunload = function(msg) {
alert(msg);
};
//API
return pub;
}());
El código que muestres,
(function (msg){alert(msg)});
(''SO'');
consisten en dos afirmaciones. La primera es una expresión que produce un objeto de función (que luego se recolectará como basura porque no se guarda). El segundo es una expresión que produce una cadena. Para aplicar la función a la cadena, debe pasar la cadena como un argumento a la función cuando se crea (que también se muestra arriba), o bien, deberá almacenar la función en una variable para poder Aplícalo más tarde, a tu antojo. Al igual que:
var f = (function (msg){alert(msg)});
f(''SO'');
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, también puede definir una función regular:
function f(msg) {alert(msg)};
f(''SO'');
En resumen de los comentarios anteriores:
function() {
alert("hello");
}();
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
(function() {
alert("hello");
})();
Esta es una función de auto-invocación, lo que significa que se crea de forma anónima y se ejecuta inmediatamente 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, más paréntesis agregados alrededor del nombre de la función: (myFunction)();
.
Hay una buena sintaxis de la función JavaScript de SO discusión .
Es una función anónima autoejecutable. El primer conjunto de paréntesis contiene las expresiones que se ejecutarán, y el segundo conjunto de paréntesis ejecuta esas expresiones.
(function () {
return ( 10 + 20 );
})();
Peter Michaux discute la diferencia en un par de paréntesis importante .
Es una construcción útil cuando se trata de 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, lo que lo hace verdaderamente privado.
Ver:
Esta respuesta no está estrictamente relacionada con la pregunta, pero podría interesarle descubrir que este tipo de función de sintaxis no es específica de las funciones. Por ejemplo, siempre podemos hacer algo como esto:
alert(
{foo: "I am foo", bar: "I am bar"}.foo
); // alerts "I am foo"
Relacionado a las funciones. Como son objetos, que heredan de Function.prototype, podemos hacer cosas como:
Function.prototype.foo = function () {
return function () {
alert("foo");
};
};
var bar = (function () {}).foo();
bar(); // alerts foo
Y ya sabes, ni siquiera tenemos que rodear las funciones con paréntesis para ejecutarlas. De todos modos, siempre que intentemos asignar el resultado a una variable.
var x = function () {} (); // this function is executed but does nothing
function () {} (); // syntax error
Otra cosa que puede hacer con las funciones, tan pronto como las declara, es invocar al new
operador sobre ellas y obtener un objeto. Los siguientes son equivalentes:
var obj = new function () {
this.foo = "bar";
};
var obj = {
foo : "bar"
};
Hay una propiedad más que tiene la función de JavaScript. Si quieres llamar recursivamente a la misma función anónima.
(function forInternalOnly(){
//you can use forInternalOnly to call this anonymous function
/// forInternalOnly can be used inside function only, like
var result = forInternalOnly();
})();
//this will not work
forInternalOnly();// no such a method exist
La simple razón por la que no funciona no es debido a la ;
indicando el final de la función anónima. Esto se debe a que sin el ()
al final de una llamada de función, no es una llamada de función. Es decir,
function help() {return true;}
Si llamas result = help();
esta es una llamada a una función y devolverá true.
Si llamas result = help;
esto no es una llamada Es una asignación en la que la ayuda se trata como datos a asignar al resultado.
Lo que hizo fue declarar / crear una instancia de una función anónima agregando el punto y coma,
(function (msg) { /* Code here */ });
y luego intenté llamarlo en otra declaración usando solo paréntesis ... Obviamente porque la función no tiene nombre, pero esto no funcionará:
(''SO'');
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í:
(function (msg){/*code here*/});(''SO'');
Todavía no funciona, pero funciona cuando se elimina el punto y coma porque el intérprete ignora los espacios en blanco y los carros y ve el código completo como una sola declaración.
(function (msg){/*code here*/}) // This space is ignored by the interpreter
(''SO'');
Conclusión: una llamada de función no es una llamada de función sin el ()
en el final a menos que bajo condiciones específicas como ser invocado por otra función, es decir, onload = ''ayuda'' ejecutaría la función de ayuda aunque no se incluyeran los paréntesis. Creo que setTimeout y setInterval también permiten este tipo de llamada de función, y también creo que el intérprete agrega los paréntesis detrás de la escena de todos modos, lo que nos lleva a "una llamada de función no es una llamada de función sin los paréntesis".
Las funciones anónimas están destinadas a ser un acuerdo de un solo disparo en el que se define una función sobre la marcha para que genere una salida de usted a partir de una entrada que está proporcionando. Excepto que usted no proporcionó la entrada. En su lugar, escribió algo en la segunda línea (''SO''); - una declaración independiente que no tiene nada que ver con la función. ¿Que esperabas? :)
Mi comprensión de la pregunta del autor de la pregunta es tal que:
¿Cómo funciona esta magia?
(function(){}) (''input'') // Used in his example
Puedo estar equivocado. Sin embargo, la práctica habitual con la que las personas están familiarizadas es:
(function(){}(''input'') )
La razón es tal que JavaScript entre paréntesis de AKA ()
, no puede contener declaraciones y cuando el analizador encuentra la palabra clave de la función, sabe analizarla como una expresión de la función y no como una declaración de la función.
Fuente: blog post Expresión de función inmediatamente invocada (IIFE)
Otro punto de vista
Primero, puedes declarar una función anónima:
var foo = function(msg){
alert(msg);
}
Entonces lo llamas:
foo (''Few'');
Porque foo = function (msg) {alert (msg);} para que puedas reemplazar foo como:
function(msg){
alert(msg);
} (''Few'');
Pero debe envolver toda su función anónima dentro de par de llaves para evitar el error de sintaxis de declarar la función al analizar. Entonces nosotros tenemos,
(function(msg){
alert(msg);
}) (''Few'');
De esta manera, es fácil de entender para mí.
Se llama una función auto-invocada.
Lo que está haciendo cuando llama (function(){})
está devolviendo un objeto de función. Cuando le agregas ()
, se invoca y se ejecuta cualquier elemento del cuerpo. El ;
denota el final de la declaración, por eso la segunda invocación falla.
Suelte el punto y coma después de la definición de la función.
(function (msg){alert(msg)})
(''SO'');
Arriba debería funcionar.
Página DEMO: https://jsfiddle.net/e7ooeq6m/
He discutido este tipo de patrón en este post:
EDITAR:
Si observa la especificación del script ECMA , hay 3 formas de definir una función. (Página 98, Sección 13 Definición de función)
1. Usando el constructor de funciones
var sum = new Function(''a'',''b'', ''return a + b;'');
alert(sum(10, 20)); //alerts 30
2. Usando la declaración de función.
function sum(a, b)
{
return a + b;
}
alert(sum(10, 10)); //Alerts 20;
3. Expresión de la función
var sum = function(a, b) { return a + b; }
alert(sum(5, 5)); // alerts 10
Así que puedes preguntar, ¿cuál es la diferencia entre declaración y expresión?
De la especificación del script de ECMA:
FunctionDeclaration: identificador de función (FormalParameterListopt) {FunctionBody}
FunctionExpression: function Identifieropt (FormalParameterListopt) {FunctionBody}
Si observa, el ''identificador'' es opcional para la expresión de la función. Y cuando no da un identificador, crea una función anónima. No significa que no pueda especificar un identificador.
Esto significa que lo siguiente es válido.
var sum = function mySum(a, b) { return a + b; }
El punto importante a tener en cuenta es que puede usar ''mySum'' solo dentro del cuerpo de la función mySum, no afuera. Vea el siguiente ejemplo:
var test1 = function test2() { alert(typeof test2); }
alert(typeof(test2)); //alerts ''undefined'', surprise!
test1(); //alerts ''function'' because test2 is a function.
Compara esto con
function test1() { alert(typeof test1) };
alert(typeof test1); //alerts ''function''
test1(); //alerts ''function''
Armados con este conocimiento, tratemos de analizar su código.
Cuando tienes código como
function(msg) { alert(msg); }
Has creado una expresión de función. Y puede ejecutar esta expresión de función envolviéndola entre paréntesis.
(function(msg) { alert(msg); })(''SO''); //alerts SO.
Una cosa que me pareció confusa es que los "()" son operadores de agrupación.
Aquí está su función básica declarada.
Ex. 1:
var message = ''SO'';
function foo(msg) {
alert(msg);
}
foo(message);
Las funciones son objetos, y se pueden agrupar. Así que vamos a lanzar parens alrededor de la función.
Ex. 2:
var message = ''SO'';
function foo(msg) { //declares foo
alert(msg);
}
(foo)(message); // calls foo
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.
var message = ''SO'';
(function foo(msg) {
alert(msg);
})(message); // declares & calls foo
Finalmente, no necesitamos ese dinero extra porque no estamos usando el nombre para llamarlo. Las funciones pueden ser anónimas.
Ex. 4.
var message = ''SO'';
(function (msg) { // remove unnecessary reference to foo
alert(msg);
})(message);
Para responder a su pregunta, refiérase al 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.)
(function (msg){alert(msg)});
(''SO''); // nothing.
(foo);
(msg); //Still nothing.
Pero
(foo)
(msg); //works
Una función anónima no es una función con el nombre "". Es simplemente una función sin nombre.
Como 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 pueden usarse:
function(){ alert("plop"); }
2;
Así que tenemos que almacenarlos en una variable para poder usarlos, como cualquier otro valor:
var f = function(){ alert("plop"); }
var n = 2;
También puedes usar azúcar sintáctica para unir la función a una variable:
function f(){ alert("plop"); }
var n = 2;
Pero si no es necesario nombrarlos y daría lugar a más confusión y menos facilidad de lectura, puede usarlos de inmediato.
(function(){ alert("plop"); })(); // will display "plop"
alert(2 + 3); // will display 5
Aquí, mi función y mis números no están vinculados a una variable, pero aún se pueden usar.
Dicho de esta manera, parece que la función de auto-invocación no tiene valor real. Pero hay que 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 auto-invocación en realidad tiene el mismo significado que un bloque C ++, C # o Java. Lo que significa que la variable creada en el interior no se "filtrará" fuera del alcance. Esto es muy útil en JavaScript para no contaminar el alcance global.
(function (msg){alert(msg)})
(''SO'');
Este es un método común de usar una función anónima como un cierre que usan muchos frameworks de JavaScript.
Esta función llamada es automáticamente cuando se compila el código.
Si se coloca ;
En la primera línea, el compilador lo trató como dos líneas diferentes. Así que no puedes obtener los mismos resultados que arriba.
Esto también se puede escribir como:
(function (msg){alert(msg)}(''SO''));
Para más detalles, mira en JavaScript / Funciones anónimas .