Pergunta

Eu estava lendo alguns posts sobre fechamentos e vi este em todos os lugares, mas não há nenhuma explicação clara como funciona - toda vez que eu estava apenas disse 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 nova função anônima e, em seguida, executá-lo. Então, depois que este simples código deve funcionar (e faz):

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

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

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

, em seguida, uma nova função sem nome seria criado como função "" (msg) ...

mas então por que isso não funciona?

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

Por que isso precisa ser na mesma linha?

Você poderia por favor me aponte algumas mensagens ou me dar uma explicação?

Foi útil?

Solução

Retirar o ponto e vírgula após a definição da função.

(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 $ perguntas

EDIT:

Se você olhar para ECMAScript especificação , existem 3 maneiras que você pode definir uma função. (Página 98, Seção 13 Função Definição)

1. Usando função de construtor

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

2. Usando declaração da função.

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

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

3. Função Expression

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

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

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

De especificação ECMA Script:

FunctionDeclaration: função Identificador (FormalParameterListopt) {FunctionBody }

FunctionExpression: função Identifieropt (FormalParameterListopt) {FunctionBody }

Se você notar, 'identificador' é opcional para a expressão de função. E quando você não dá um identificador, você cria uma função anônima. Isso não significa que você não pode especificar um identificador.

Isto significa que se segue é válido.

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

ponto importante a notar é que você pode usar 'mySum' apenas dentro do corpo da função mySum, não fora. Veja o exemplo seguinte:

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'

Com este conhecimento, vamos tentar analisar seu código.

Quando você tem um código como,

    function(msg) { alert(msg); }

Você criou uma expressão de função. E você pode executar essa expressão da função por envolvê-lo dentro de parênteses.

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

Outras dicas

É chamado uma função de auto-invocado.

O que você está fazendo quando você chamar (function(){}) está retornando um objeto de função. Quando você anexar () para ele, ele é invocado e qualquer coisa no corpo é executado. O ; denota o fim da instrução, é por isso que a 2ª chamada falhar.

Uma coisa que eu achei confuso é que os operadores "()" são agrupamento.

Aqui está a sua função declarada básico.

Ex. 1:

var message = 'SO';

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

foo(message);

As funções são objetos, e podem ser agrupadas. Então vamos jogar parênteses em torno da função.

Ex. 2:

var message = 'SO';

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

(foo)(message);     // calls foo

Agora, em vez de declarar e direita-away chamando a mesma função, podemos usar substituição básico para declará-la como o chamamos.

Ex. 3.

var message = 'SO';

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

Finalmente, não temos uma necessidade para que foo extra, porque nós não estamos usando o nome de chamá-lo! As 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, remeter para Exemplo 2. Sua primeira linha declara uma função sem nome e os grupos de TI, mas não chamá-lo. Os segundos grupos de linha de uma corda. Ambos não fazer nada. (Primeiro exemplo de Vincent.)

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

(foo); 
(msg); //Still nothing.

Mas

(foo)
(msg); //works

Uma função anônima não é uma função com o nome "". É simplesmente uma função sem um nome.

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

Mas, como qualquer outro valor, às vezes você quiser usá-lo sem ligação-lo para um nome. Esse é o padrão de auto-invocando.

Aqui é uma função e um número, não ligados, eles não fazem nada e nunca pode ser usado:

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

Por isso temos de armazená-los em uma variável para ser capaz de 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 função a uma variável:

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

Mas se nomeá-los não é necessário e levaria a mais confusão e menos legibilidade, você pode simplesmente usá-los imediatamente.

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

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

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

Assim, uma função de auto-invocando realmente tem o mesmo significado como C ++, C # ou bloco Java. O que significa que variável criada dentro não vai "vazar" fora do escopo. Isto é muito útil em JavaScript, a fim de não poluir o escopo global.

É apenas como JavaScript funciona. Você pode declarar uma função chamada:

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

E chamá-lo:

foo("Hi!");

Ou, você pode declarar uma função anônima:

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

e chamar isso:

foo("Hi!");

Ou, você pode simplesmente nunca ligam a função a um nome:

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

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

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

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

Vale a pena nada que quaisquer variáveis ??definidas com "var" no corpo de make_foo será fechada ao longo de cada função retornado por make_foo. Este é um fechamento, e isso significa que a qualquer alteração feita ao valor em uma função será visível por outro.

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

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

var hello = make_greeter("Hello!");

hello();

É apenas como quase toda linguagem de programação Java, mas funciona.

O código que você mostrar,

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

consistem em dois declarações. A primeira é uma expressão que produz um objecto de função (que será, em seguida, ser recolhido o lixo, porque não é guardada). A segunda é uma expressão que produz uma cadeia de caracteres. Para aplicar a função para a cadeia, você quer necessidade de passar a cadeia como um argumento para a função quando ele é criado (que você também mostram acima), ou você terá que realmente armazenar a função em uma variável, de modo que você pode aplicá-lo em um momento posterior, em seu lazer. Como assim:

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

Note que, armazenando uma função anônima (uma função lambda) em uma variável, você está dando-lhe efetivamente um nome. Daí você pode muito bem definir uma função normal:

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

Em resumo dos comentários anteriores:

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

quando não estiver atribuído a uma variável, produz um erro de sintaxe. O código é analisado como uma declaração de função (ou definição), o que torna os parênteses de fechamento sintaticamente incorreto. Adicionando parênteses ao redor da porção função diz ao intérprete (e programador) que esta é uma expressão de função (ou invocação), como em

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

Esta é uma função de auto-invocando, o que significa que é criado de forma anônima e executado imediatamente, porque a invocação acontece na mesma linha onde ele é declarado. Esta função auto-invocando é indicado com a sintaxe familiar para chamar uma função sem argumentos, além de parênteses adicionado ao redor do nome da função:. (myFunction)();

uma discussão boa SO JavaScript sintaxe da função .

Esta resposta é não estritamente relacionadas com a pergunta, mas você pode estar interessado em saber que este tipo de recurso sintaxe não é específico para as funções. Por exemplo, podemos sempre fazer algo como isto:

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

relacionadas às funções. Como eles são objetos, 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, nós nem sequer têm a funções surround com parênteses, a fim de executá-los. De qualquer forma, enquanto nós tentamos 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 declará-los, é invocar o operador new sobre eles e obter um objeto. A seguir são equivalentes:

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

var obj = {
    foo : "bar"
};

Há mais uma propriedade de função JavaScript tem. Se você quiser chamar mesma função 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

O meu entendimento da pergunta do autor da questão é tal que:

Como funciona este mágico:

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

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

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

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

Fonte: blog Função Imediatamente-Chamado Expressão ( IIFE)

exemplos sem parênteses:

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

(este é o único uso real do vazio, afaik)

ou

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

ou

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

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

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

É uma função anônima auto-executada. O primeiro conjunto de suportes contêm as expressões a serem executados, e o segundo conjunto de suportes executa essas expressões.

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

Peter Michaux discute a diferença na Um par importante de Parênteses .

É uma construção útil quando se tenta ocultar variáveis ??do namespace pai. Todo o código dentro da função está contida no âmbito privado da função, o que significa que não pode ser acessado em tudo do lado de fora da função, tornando-o verdadeiramente privada.

Veja:

  1. Encerramento (informática)
  2. JavaScript namespacing
  3. Importante Par de Javascript Parênteses

Outro ponto de vista

Em primeiro lugar, você pode declarar uma função anônima:

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

Em seguida, você chamá-lo:

foo ('Few');

Como foo = function (msg) {alert (msg);} para que você possa substituir foo como:

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

Mas você deve envolver toda a sua função dentro par anônima de chaves para evitar erro de sintaxe de declaração de função ao analisar. Então nós temos,

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

Desta forma, é fácil entender por mim.

Quando você fez:

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

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

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

Ele vai trabalhar.

Working exemplo: http://jsfiddle.net/oliverni/dbVjg/

A simples razão por que ele não funciona não é por causa da ; indicando o fim da função anônima. É porque sem a () no final de uma chamada de função, não é uma chamada de função. Ou seja,

function help() {return true;}

Se você chamar result = help(); esta é uma chamada para uma função e irá retornar verdadeiro.

Se você chamar result = help; isso não é uma chamada. É um trabalho onde a ajuda é tratado como dados a serem atribuídas aos resultados.

O que você fez foi declarar / instanciar uma função 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 função não tem nome, mas isso não vai funcionar:

('SO');

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

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

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

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

Conclusão: uma chamada de função não é uma chamada de função sem a () na extremidade a menos que sob condições específicas, como está sendo chamado por outra função, ou seja, onload = 'ajuda' iria executar a função de ajuda, mesmo que os parênteses não foram incluído. Acredito setTimeout e setInterval também permitem este tipo de chamada de função também, e eu também acredito que o intérprete adiciona os parênteses nos bastidores em todo o caso que nos traz de volta a "uma chamada de função não é uma chamada de função, sem os parênteses".

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

Este é um método comum de usar uma função anônima como um fechamento que muitos frameworks JavaScript usar.

Esta função chamada é automaticamente quando o código é compilado.

Se colocando ; na primeira linha, o compilador tratado como duas linhas diferentes. Então você não pode obter os mesmos resultados como acima.

Isto pode também ser escrita como:

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

Para obter mais detalhes, olhar em JavaScript / anônimos Funções .

  1. funções anônimas são funções que são declaradas dinamicamente em tempo de execução. Eles são chamados de funções anônimas, porque não são dado um nome da mesma maneira como funções normais.

    funções

    anônimos são declarados usando o operador de função em vez da declaração da função. Você pode usar o operador de função para criar uma nova função onde quer que seja válida para colocar uma expressão. Para exemplo, você poderia declarar uma nova função como um parâmetro para um chamada de função ou atribuir uma propriedade de outro objeto.

    Aqui está um exemplo típico de uma função chamada:

    função flyToTheMoon () {alert ( "Zoom Zoom Zoom!"); } flyToTheMoon (); Aqui está o mesmo exemplo criado como um anônimo função:

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

    Para obter mais informações, por favor leia aqui:

    http://helephant.com/2008/08/23/javascript -Anonymous-funções /

O IIFE simplesmente compartimenta a função e se esconde a variável msg de modo a não "poluir" o namespace global. Na realidade, apenas mantê-la simples e gosto de seguir a menos que você está construindo um site de bilhões de dólares.

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

Você poderia namespace sua propriedade msg usando um Padrão Módulo Revelando como:

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

Funções anônimas são destinadas a ser one-shot negócio, onde você define uma função em tempo real para que ele gera uma saída de você de uma entrada que você está fornecendo. Exceto que você não forneceu a entrada. Em vez disso, você escreveu alguma coisa na segunda linha ( 'SO'); - uma declaração independente que não tem nada a ver com a função. O que você esperava? :)

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top