Pregunta

Estuve leyendo algunas publicaciones sobre cierres y vi esto en todas partes, pero no hay una explicación clara de cómo funciona; cada vez 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 funciona):

(function (msg){alert(msg)})('SO');

Mi pregunta es ¿qué tipo de magia ocurre aquí?Pensé eso 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é tiene que estar en la misma línea?

¿Podrías indicarme algunas publicaciones o darme una explicación?

¿Fue útil?

Solución

La caída de la coma después de la definición de la función.

(function (msg){alert(msg)})
('SO');

Sobre debería funcionar.

DEMO página: https://jsfiddle.net/e7ooeq6m/

He discutido este tipo de patrón en este post:

jQuery y $ preguntas

EDIT:

Si nos fijamos en especificación ECMA guión , hay 3 formas en que puede definir una función. (Página 98, Sección 13 Definición de la función)

1. Uso de la función constructor

var sum = new Function('a','b', 'return a + b;');
alert(sum(10, 20)); //alerts 30

2. Usando declaración de la función.

function sum(a, b)
{
    return a + b;
}

alert(sum(10, 10)); //Alerts 20;

3. Expresión de función

var sum = function(a, b) { return a + b; }

alert(sum(5, 5)); // alerts 10

Así que usted puede preguntar, ¿cuál es la diferencia entre la declaración y la expresión?

A partir de la especificación ECMA script:

  

FunctionDeclaration:       Identificador de función (FormalParameterListopt) {FunctionBody   }

     

FunctionExpression:       funcionar Identifieropt (FormalParameterListopt) {FunctionBody   }

Si se fijan, 'identificador' es opcional para la expresión de la función. Y cuando usted no da un identificador, se crea una función anónima. Esto no quiere decir que no se puede especificar un identificador.

Esto significa siguiente es válido.

var sum = function mySum(a, b) { return a + b; }

Un punto importante a destacar es que se puede utilizar 'mySum' sólo dentro del cuerpo de la función mySum, no afuera. Véase el siguiente ejemplo:

var test1 = function test2() { alert(typeof test2); }

alert(typeof(test2)); //alerts 'undefined', surprise! 

test1(); //alerts 'function' because test2 is a function.

Demo en vivo

Compare esto con

 function test1() { alert(typeof test1) };

 alert(typeof test1); //alerts 'function'

 test1(); //alerts 'function'

Armado con este conocimiento, vamos a tratar de analizar su código.

Cuando usted tiene un código como,

    function(msg) { alert(msg); }

Se creó una expresión de función. Y se puede ejecutar esta expresión de función envolviéndolo entre paréntesis.

    (function(msg) { alert(msg); })('SO'); //alerts SO.

Otros consejos

Se llama una función de auto-invocado.

Lo que está haciendo cuando se llama (function(){}) devuelve un objeto de función. Cuando anexa () a ella, se invoca y se ejecuta nada en el cuerpo. El ; indica el final de la declaración, por eso no pasa la segunda invocación.

Una cosa que me pareció confuso es que los operadores "()" se agrupan.

Aquí está su función declarada básica.

Ex. 1:

var message = 'SO';

function foo(msg) {
    alert(msg);
}

foo(message);

Las funciones son objetos, y se pueden agrupar. Así que vamos a tirar 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 derecha, lejos llamando a la misma función, se puede utilizar la sustitución básica para declarar como lo llamamos.

Ex. 3.

var message = 'SO';

(function foo(msg) {
    alert(msg);
})(message);          // declares & calls foo

Por último, no tenemos la necesidad de que foo extra porque no estamos usando el nombre para llamarlo! Las funciones pueden ser anónimos.

Ex. 4.

var message = 'SO';

(function (msg) {   // remove unnecessary reference to foo
    alert(msg);
})(message);

Para responder a su pregunta, referirse de nuevo al ejemplo 2. Su primera línea declara alguna función y grupos sin nombre, pero no lo llama. El segundo grupos de líneas una cadena. Ambos hacen nada. (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.

Al igual que cualquier otro valor en JavaScript, una función no necesita un nombre que se creará. A pesar de que es mucho más útil que en realidad se unen a un nombre como cualquier otro valor.

Sin embargo, como cualquier otro valor, a veces se desea utilizarlo sin unirse a un nombre. Ese es el patrón de auto-invocando.

Aquí es una función y un número, no obligado, no hacen nada y nunca se pueden utilizar:

function(){ alert("plop"); }
2;

Así que tenemos que guardarlos en una variable para poder utilizarlos, al igual que cualquier otro valor:

var f = function(){ alert("plop"); }
var n = 2;

También puede utilizar el azúcar sintáctico para obligar a la función a una variable:

function f(){ alert("plop"); }
var n = 2;

Pero si nombrarlos no es necesario y podría dar lugar a una mayor confusión y menos legibilidad, sólo podría utilizar de inmediato.

(function(){ alert("plop"); })(); // will display "plop"
alert(2 + 3); // will display 5

A continuación, mi función y mis números no están vinculados a una variable, pero todavía pueden ser utilizados.

Dicho así, parece que la función de auto-invocando tiene ningún valor real. Pero hay que tener en cuenta que JavaScript alcance delimitador es la función y no el bloque ({}).

Por lo tanto una función de auto-invocando realidad tiene el mismo significado como C ++, C # o Java bloque. Lo que significa que la variable no será creado dentro de "fuga" fuera del alcance. Esto es muy útil en JavaScript con el fin de no contaminar el ámbito global.

Es sólo cómo funciona JavaScript. Se puede declarar una función llamada:

function foo(msg){
   alert(msg);
}

Y llamarlo:

foo("Hi!");

O, se puede declarar una función anónima:

var foo = function (msg) {
    alert(msg);
}

Y llama que:

foo("Hi!");

O, nunca se puede obligar a la función a un nombre:

(function(msg){
   alert(msg);
 })("Hi!");

Las funciones también pueden volver funciones:

function make_foo() {
    return function(msg){ alert(msg) };
}

(make_foo())("Hi!");

Es destacable que las variables definidas con "var" en el cuerpo de make_foo se cerraron sobre por cada función que devuelve make_foo. Esto es un cierre, y significa que el cualquier cambio realizado en el valor en una función será visible por otro.

Esto le permite encapsular la información, si lo desea:

function make_greeter(msg){
    return function() { alert(msg) };
}

var hello = make_greeter("Hello!");

hello();

Es sólo la forma en casi cualquier lenguaje de programación Java, pero funciona.

El código de mostrar,

(function (msg){alert(msg)});
('SO');

dos declaraciones. La primera es una expresión que se obtiene un objeto de función (que a continuación se recoge la basura, porque no se guarda). La segunda es una expresión que produce una cadena. Para aplicar la función a la cadena, o hay que hacer pasar la cadena como un argumento a la función cuando se crea (que también se muestra arriba), o tendrá que almacenar en realidad la función de una variable, para que pueda aplicarlo en un momento posterior, en su tiempo libre. De esta manera:

var f = (function (msg){alert(msg)});
f('SO');

Tenga en cuenta que mediante el almacenamiento de una función anónima (una función lambda) en una variable, su están efectivamente dándole un nombre. Por lo tanto es posible que al igual que definir así una función regular:

function f(msg) {alert(msg)};
f('SO');

En resumen de los comentarios anteriores:

function() {
  alert("hello");
}();

cuando no asignado a una variable, se obtiene un error de sintaxis. El código se analiza como una sentencia de función (o definición), que hace que el cierre de paréntesis sintácticamente incorrecta. Adición de paréntesis alrededor de la porción función dice al intérprete (y programador) que se trata de una expresión de función (o invocación), como en

(function() {
  alert("hello");
})();

Esta es una función de auto-invocando, lo que significa que se crea de forma anónima y se ejecuta inmediatamente debido a la invocación que ocurre en la misma línea en la que 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 añadió paréntesis alrededor del nombre de la función:. (myFunction)();

Hay un buen SO discusión JavaScript sintaxis de la función.

Esta respuesta no está estrictamente relacionada con la cuestión, pero que podría estar interesado para saber que este tipo de característica de sintaxis no es particular de funciones. Por ejemplo, siempre se puede hacer algo como esto:

alert(
    {foo: "I am foo", bar: "I am bar"}.foo
); // alerts "I am foo"

En relación con las funciones. Ya que 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, que no tienen ni siquiera para rodear funciones con paréntesis para ejecutarlos. De todos modos, siempre y cuando tratamos de 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, en cuanto se declaran, es invocar el operador new sobre ellos y obtener un objeto. Los siguientes son equivalentes:

var obj = new function () {
    this.foo = "bar";
};

var obj = {
    foo : "bar"
};

Hay una propiedad de más de JavaScript tiene. Si desea llamar misma función anónima recursiva.

(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

Mi comprensión de la pregunta del autor de la pregunta es tal que:

¿Cómo funciona la magia:

(function(){}) ('input')   // Used in his example

Puede que me equivoque. Sin embargo, la práctica habitual que las personas están familiarizados es:

(function(){}('input') )

La razón es tal que JavaScript paréntesis También conocido como (), no puede contener declaraciones y cuando el analizador encuentra la palabra clave function, se sabe que analizar como una expresión de función y no una declaración de la función.

Fuente: blog llamada inmediatamente-expresión de función ( IIFE)

ejemplos sin paréntesis:

void function (msg) { alert(msg); }
('SO');

(este es el único uso real del vacío, que yo sepa)

o

var a = function (msg) { alert(msg); }
('SO');

o

!function (msg) { alert(msg); }
('SO');

trabajo también. la void está causando la expresión de 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 trabajo son de ++ Couse, -- debido a la exigencia de una variable.

el salto de línea no es necesario.

Se trata de una función anónima autoejecutable. El primer conjunto de soportes contiene las expresiones a ser ejecutados, y el segundo conjunto de corchetes realiza esas expresiones.

(function () {
    return ( 10 + 20 );
})();

Pedro Michaux analiza la diferencia en Un par adicional de paréntesis .

Es un constructo útil cuando se trata de ocultar las variables del espacio de nombres de los padres. Todo el código dentro de la función está contenida en el ámbito privado de la función, lo que significa que no se puede acceder a todo desde fuera de la función, por lo que es verdaderamente privadas.

Ver:

  1. Cierre (informática)
  2. JavaScript namespacing
  3. par adicional de Javascript paréntesis

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 = función(msg){alerta(msg);} para que puedas reemplazar foo como:

function(msg){
 alert(msg);
} ('Few');

Pero debe envolver toda su función anónima dentro de un par de llaves para evitar errores de sintaxis al declarar la función al analizar.Entonces nosotros tenemos,

(function(msg){
 alert(msg);
}) ('Few');

De esta manera, es fácil de entender para mí.

Cuando lo hizo:

(function (msg){alert(msg)});
('SO');

Se terminó la función antes ('SO') debido a la coma. Si usted acaba de escribir:

(function (msg){alert(msg)})
('SO');

Se va a funcionar.

Ejemplo de trabajo: http://jsfiddle.net/oliverni/dbVjg/

El simple razón por la que no funciona no se debe a la ; que indica el final de la función anónima. Es porque sin el () en el extremo de una llamada de función, que no es una llamada a la función. Es decir,

function help() {return true;}

Si llama result = help(); esto es una llamada a una función y volverá realidad.

Si llama result = help; esto no es una llamada. Es una misión donde la ayuda es tratado como datos para ser asignados a resultar.

Lo que se hizo fue declarar / instanciar una función anónima añadiendo el punto y coma,

(function (msg) { /* Code here */ });

y luego trató de llamarlo en otro comunicado utilizando sólo los paréntesis ... Obviamente porque la función no tiene nombre, pero esto no va a 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 quita el punto y coma porque el intérprete ignora los espacios en blanco y los carros y ve el código completo como una 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 a la función sin la () en el extremo menos que bajo condiciones específicas, como ser invocado por otra función, es decir, onload = 'ayuda' se ejecutará la función de ayuda a pesar de que los paréntesis no eran incluido. Creo setTimeout y setInterval también permiten este tipo de llamada a la función también, y también creo que el intérprete añade entre paréntesis detrás de las escenas de todos modos lo que nos lleva de nuevo a "una llamada de función no es una llamada a la función sin los paréntesis".

(function (msg){alert(msg)})
('SO');

Este es un método común de utilizar una función anónima como un cierre que utilizan muchos marcos de JavaScript.

Esta función llamada es automáticamente cuando se compila el código.

Si la colocación de ; en la primera línea, el compilador trató como dos líneas diferentes. Por lo que no puede obtener los mismos resultados que el anterior.

Esto también se puede escribir como:

(function (msg){alert(msg)}('SO'));

Para más detalles, mira en Funciones JavaScript / anónimos .

  1. Las funciones anónimas son funciones que se declaran de forma dinámica en tiempo de ejecución. Se llaman funciones anónimas porque no están dado un nombre en la misma forma que las funciones normales.

    Las funciones anónimas se declaran usando el operador de función en lugar de la declaración de la función. Se puede utilizar el operador de la función de crear una nueva función dondequiera que sea válida para poner una expresión. por ejemplo, usted podría declarar una nueva función como un parámetro a una función de llamada o para asignar una propiedad de otro objeto.

    Este es un ejemplo típico de una función llamada:

    Función flyToTheMoon () {alert ( "Zoom Zoom Zoom!!!"); } volar a la luna(); Aquí está el mismo ejemplo creada como un anónimo Función:

    var flyToTheMoon = function () {alert ( "Zoom Zoom Zoom!!!"); } flyToTheMoon ();

    Para más detalles por favor lea aquí:

    http://helephant.com/2008/08/23/javascript -Anónimo-funciones /

El IIFE simplemente compartimenta la función y la variable oculta msg para no "contaminar" el espacio de nombres global. En realidad, tal que sea simple y hacer como continuación a menos que usted está construyendo un sitio web de mil millones de dólares.

var msg = "later dude";
window.onunload = function(msg){
  alert( msg );
};

Se podría namespace su propiedad msg utilizando un Revelando el diseño del módulo como:

var myScript = (function() {
    var pub = {};
    //myscript.msg
    pub.msg = "later dude";
    window.onunload = function(msg) {
        alert(msg);
    };
    //API
    return pub;
}());

Las funciones anónimas están destinados a ser asunto de una sola donde se define una función sobre la marcha para que genere una salida de usted de una entrada que está proporcionando. Excepto que usted no proporcionó la entrada. En su lugar, usted escribió algo en la segunda línea ( 'SO'); - una declaración independiente que no tiene nada que ver con la función. ¿Que esperabas? :)

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top