Por que você precisa invocar uma function anônima na mesma linha?

Eu estava lendo alguns posts sobre encerramentos e vi isso em todos os lugares, mas não há nenhuma explicação clara de como funciona – toda vez que me disseram para usá-lo …:

// 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, vejo que vamos criar uma nova function anônima e depois executá-la. Então, depois disso, esse código simples deve funcionar (e funciona):

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

Minha pergunta é que tipo de mágica acontece aqui? Eu pensei que quando eu escrevi:

 (function (msg){alert(msg)}) 

então uma nova function sem nome seria criada como function “” (msg) …

mas por que isso não funciona?

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

Por que precisa estar na mesma linha?

Poderia, por favor, me apontar alguns posts ou me dar uma explicação?

Solte o ponto e vírgula após a definição da function.

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

Acima deve funcionar.

Página de demonstração: https://jsfiddle.net/e7ooeq6m/

Eu discuti esse tipo de padrão neste post:

jQuery e $ questions

EDITAR:

Se você observar a especificação do script ECMA , existem 3 maneiras de definir uma function. (Página 98, seção 13 definição de function)

1. Usando o Construtor de Função

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

2. Usando declaração de function.

 function sum(a, b) { return a + b; } alert(sum(10, 10)); //Alerts 20; 

3. Expressão de Função

 var sum = function(a, b) { return a + b; } alert(sum(5, 5)); // alerts 10 

Então você pode perguntar, qual é a diferença entre declaração e expressão?

Da especificação do script ECMA:

FunctionDeclaration: function Identifier (FormalParameterListopt) {FunctionBody}

FunctionExpression: function Identifieropt (FormalParameterListopt) {FunctionBody}

Se você perceber, ‘identificador’ é opcional para a expressão de function. E quando você não dá um identificador, você cria uma function anônima. Isso não significa que você não pode especificar um identificador.

Isso significa que seguir é válido.

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

Um ponto importante a ser observado é que você pode usar ‘mySum’ somente dentro do corpo da function mySum, e não fora dele. Veja o exemplo a seguir:

 var test1 = function test2() { alert(typeof test2); } alert(typeof(test2)); //alerts 'undefined', surprise! test1(); //alerts 'function' because test2 is a function. 

Demonstração ao vivo

Compare isso com

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

Armado com esse conhecimento, vamos tentar analisar seu código.

Quando você tem código como

  function(msg) { alert(msg); } 

Você criou uma expressão de function. E você pode executar essa expressão de function colocando-a entre parênteses.

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

É chamado de uma function auto-invocada.

O que você está fazendo quando chama (function(){}) está retornando um object de function. Quando você anexa () a ele, ele é invocado e qualquer coisa no corpo é executada. O ; denota o fim da declaração, é por isso que a segunda invocação falha.

Uma coisa que achei confusa é que os “()” são operadores de agrupamento.

Aqui está sua function declarada básica.

Ex. 1:

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

Funções são objects e podem ser agrupadas. Então, vamos jogar parênteses em torno da function.

Ex. 2:

 var message = 'SO'; function foo(msg) { //declares foo alert(msg); } (foo)(message); // calls foo 

Agora, em vez de declarar e imediatamente chamar a mesma function, podemos usar a substituição básica para declará-la como a chamamos.

Ex. 3

 var message = 'SO'; (function foo(msg) { alert(msg); })(message); // declares & calls foo 

Finalmente, nós não temos necessidade desse extra foo porque não estamos usando o nome para chamá-lo! Funções podem ser anônimas.

Ex. 4

 var message = 'SO'; (function (msg) { // remove unnecessary reference to foo alert(msg); })(message); 

Para responder à sua pergunta, refira-se ao Exemplo 2. Sua primeira linha declara alguma function sem nome e a agrupa, mas não a chama. A segunda linha agrupa uma string. Ambos não fazem nada. (O primeiro exemplo de Vincent)

 (function (msg){alert(msg)}); ('SO'); // nothing. (foo); (msg); //Still nothing. 

Mas

 (foo) (msg); //works 

Uma function anônima não é uma function com o nome “”. É simplesmente uma function sem nome.

Como qualquer outro valor em JavaScript, uma function não precisa de um nome para ser criada. Embora seja muito mais útil vinculá-lo a um nome como qualquer outro valor.

Mas, como qualquer outro valor, às vezes você quer usá-lo sem vinculá-lo a um nome. Esse é o padrão de auto-invocação.

Aqui está uma function e um número, não vinculado, eles não fazem nada e nunca podem ser usados:

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

Então temos que armazená-los em uma variável para poder usá-los, assim como qualquer outro valor:

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

Você também pode usar o açúcar sintático para vincular a function a uma variável:

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

Mas se nomenciá-los não for necessário e levar a mais confusão e menos legibilidade, você poderá usá-los imediatamente.

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

Aqui, minha function e meus números não estão vinculados a uma variável, mas eles ainda podem ser usados.

Dito assim, parece que a function auto-invocadora não tem valor real. Mas você deve ter em mente que o delimitador de escopo de JavaScript é a function e não o bloco ({}).

Portanto, uma function de auto-invocação realmente tem o mesmo significado que um bloco C ++, C # ou Java. O que significa que a variável criada dentro não “vazará” fora do escopo. Isso é muito útil em JavaScript para não poluir o escopo global.

É como o JavaScript funciona. Você pode declarar uma function nomeada:

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

E chame isso:

 foo("Hi!"); 

Ou você pode declarar uma function anônima:

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

E chame isso:

 foo("Hi!"); 

Ou você nunca pode vincular a function a um nome:

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

Funções também podem retornar funções:

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

Não vale a pena nada que quaisquer variables ​​definidas com “var” no corpo de make_foo sejam fechadas por cada function retornada por make_foo . Isso é um fechamento e significa que qualquer alteração feita no valor por uma function será visível por outra.

Isso permite encapsular informações, se você desejar:

 function make_greeter(msg){ return function() { alert(msg) }; } var hello = make_greeter("Hello!"); hello(); 

É exatamente como quase toda linguagem de programação, exceto Java, funciona.

O código que você mostra

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

consistem em duas declarações. A primeira é uma expressão que produz um object de function (que será então coletado como lixo porque não é salvo). A segunda é uma expressão que produz uma string. Para aplicar a function à string, você precisa passar a string como um argumento para a function quando ela é criada (o que você também mostra acima), ou você precisará realmente armazenar a function em uma variável, para que você possa aplique-o mais tarde, no seu tempo livre. Igual a:

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

Note que, ao armazenar uma function anônima (uma function lambda) em uma variável, você está efetivamente atribuindo a ela um nome. Portanto, você pode definir uma function regular:

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

Em resumo dos comentários anteriores:

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

quando não atribuído a uma variável, produz um erro de syntax. O código é analisado como uma instrução de function (ou definição), que torna os parênteses de fechamento sintaticamente incorretos. Adicionar parênteses ao redor da parte da function diz ao interpretador (e ao programador) que esta é uma expressão de function (ou invocação), como em

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

Esta é uma function de auto-invocação, o que significa que é criada anonimamente e é executada imediatamente porque a invocação acontece na mesma linha em que é declarada. Essa function de auto-invocação é indicada com a syntax familiar para chamar uma function sem argumento, além de parênteses adicionados ao redor do nome da function: (myFunction)(); .

Há uma boa syntax de function JavaScript de discussão SO .

Essa resposta não está estritamente relacionada à pergunta, mas você pode estar interessado em descobrir que esse tipo de recurso de syntax não é específico das funções. Por exemplo, podemos sempre fazer algo assim:

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

Relacionado a funções. Como são objects, que herdam de Function.prototype, podemos fazer coisas como:

 Function.prototype.foo = function () { return function () { alert("foo"); }; }; var bar = (function () {}).foo(); bar(); // alerts foo 

E você sabe, nem precisamos cercar as funções com parênteses para executá-las. De qualquer forma, desde que tentemos atribuir o resultado a uma variável.

 var x = function () {} (); // this function is executed but does nothing function () {} (); // syntax error 

Uma outra coisa que você pode fazer com funções, assim que as declara, é invocar o new operador sobre elas e obter um object. Os seguintes são equivalentes:

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

Há mais uma propriedade que a function JavaScript possui. Se você quiser chamar a mesma function anônima recursivamente.

 (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 

Meu entendimento da pergunta do solicitante é tal que:

Como essa mágica funciona:

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

Eu posso estar errado. No entanto, a prática usual com a qual as pessoas estão familiarizadas é:

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

A razão é tal que os parênteses JavaScript AKA () , não podem conter instruções e quando o analisador encontra a palavra-chave function, ele sabe analisá-lo como uma expressão de function e não como uma declaração de function.

Fonte: post no blog Expressão de Função Imediatamente Invocada (IIFE)

exemplos sem colchetes:

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

(este é o único uso real de void, afaik)

ou

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

ou

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

trabalhe também. o void está causando a expressão para avaliar, bem como a atribuição e o estrondo. o último trabalha com ~ , + , - , delete , typeof , alguns dos operadores unários ( void é um). não está funcionando são couse ++ , -- por causa da exigência de uma variável.

a quebra de linha não é necessária.

É uma function anônima auto-executável. O primeiro conjunto de colchetes contém as expressões a serem executadas e o segundo conjunto de colchetes executa essas expressões.

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

Peter Michaux discute a diferença em um par importante de parênteses .

É uma construção útil ao tentar ocultar variables ​​do namespace pai. Todo o código dentro da function está contido no escopo privado da function, o que significa que não pode ser acessado de forma alguma fora da function, tornando-a verdadeiramente privada.

Vejo:

  1. Encerramento (ciência da computação)
  2. Namespacing JavaScript
  3. Par importante de parênteses de Javascript

Outro ponto de vista

Primeiro, você pode declarar uma function anônima:

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

Então você chama isso:

 foo ('Few'); 

Porque foo = function (msg) {alert (msg);} então você pode replace foo como:

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

Mas você deve envolver toda a function anônima dentro do par de chaves para evitar erros de syntax ao declarar a function durante a análise. Então nós temos,

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

Desta forma, é fácil entender para mim.

Quando você fez:

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

Você terminou a function antes ('SO') por causa do ponto e vírgula. Se você acabou de escrever:

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

Vai funcionar.

Exemplo de trabalho: http://jsfiddle.net/oliverni/dbVjg/

A simples razão pela qual não funciona não é por causa do ; indicando o fim da function anônima. É porque sem o () no final de uma chamada de function, não é uma chamada de function. Isso é,

 function help() {return true;} 

Se você chamar result = help(); esta é uma chamada para uma function e retornará verdadeira.

Se você chamar result = help; isso não é uma binding. É uma atribuição em que a ajuda é tratada como dados a serem atribuídos ao resultado.

O que você fez foi declarar / instanciar uma function anônima adicionando o ponto-e-vírgula,

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

e, em seguida, tentou chamá-lo em outra declaração usando apenas parênteses … Obviamente, porque a function não tem nome, mas isso não funcionará:

 ('SO'); 

O interpretador vê os parênteses na segunda linha como uma nova instrução / instrução e, portanto, não funciona, mesmo se você fez assim:

 (function (msg){/*code here*/});('SO'); 

Ele ainda não funciona, mas funciona quando você remove o ponto-e-vírgula porque o interpretador ignora espaços em branco e carruagens e vê o código completo como uma instrução.

 (function (msg){/*code here*/}) // This space is ignored by the interpreter ('SO'); 

Conclusão: uma chamada de function não é uma chamada de function sem o () no final, a menos que sob condições específicas, como ser chamado por outra function, isto é, onload = ‘help’ executaria a function de ajuda mesmo que os parênteses não fossem incluídos. Acredito que setTimeout e setInterval também permitem esse tipo de chamada de function também, e eu também acredito que o interpretador adiciona os parênteses nos bastidores de qualquer forma que nos traz de volta para “uma chamada de function não é uma chamada de function sem os parênteses”.

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

Esse é um método comum de usar uma function anônima como um encerramento que muitas estruturas JavaScript usam.

Essa function é chamada automaticamente quando o código é compilado.

Se colocar ; Na primeira linha, o compilador tratou-o como duas linhas diferentes. Então você não pode obter os mesmos resultados acima.

Isso também pode ser escrito como:

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

Para mais detalhes, procure em JavaScript / Funções Anônimas .

  1. Funções anônimas são funções que são declaradas dinamicamente no tempo de execução. Eles são chamados de funções anônimas porque não recebem um nome da mesma maneira que as funções normais.

    Funções anônimas são declaradas usando o operador de function em vez da declaração da function. Você pode usar o operador de function para criar uma nova function onde for válido colocar uma expressão. Por exemplo, você poderia declarar uma nova function como um parâmetro para uma chamada de function ou para atribuir uma propriedade de outro object.

    Aqui está um exemplo típico de uma function nomeada:

    function flyToTheMoon () {alert (“Zoom! Zoom! Zoom!”); } flyToTheMoon (); Aqui está o mesmo exemplo criado como uma function anônima:

    var flyToTheMoon = function () {alerta (“Zoom! Zoom! Zoom!”); } flyToTheMoon ();

    Para mais detalhes, por favor leia aqui:

    http://helephant.com/2008/08/23/javascript-anonymous-functions/

O IIFE simplesmente compartimentaliza a function e oculta a variável msg para não “poluir” o namespace global. Na realidade, basta mantê-lo simples e fazer como abaixo, a menos que você esteja construindo um site bilionário.

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

Você poderia namespace sua propriedade msg usando um padrão de módulo de revelação como:

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

As funções anônimas são feitas para uma única transação em que você define uma function em tempo real para gerar uma saída sua a partir de uma input que você está fornecendo. Exceto que você não forneceu a input. Em vez disso, você escreveu algo na segunda linha (‘SO’); – uma declaração independente que não tem nada a ver com a function. O que você esperava? 🙂