Sintaxe de invocação de função imediata

110

Há uma opção JSLint , uma das boas partes na verdade, que "[requer] parênteses em torno de invocações imediatas", o que significa que a construção

(function () {

  // ...

})();

em vez disso, precisaria ser escrito como

(function () {

  // ...

}());

Minha pergunta é a seguinte - alguém pode explicar por que essa segunda forma pode ser considerada melhor? É mais resiliente? Menos sujeito a erros? Qual a vantagem disso sobre a primeira forma?


Depois de fazer essa pergunta, passei a compreender a importância de se ter uma distinção visual clara entre os valores das funções e os valores das funções. Considere o caso em que o resultado da invocação imediata é o lado direito de uma expressão de atribuição:

var someVar = (function () {

  // ...

}());

Embora os parênteses mais externos sejam sintaticamente desnecessários, o parêntese de abertura fornece uma indicação inicial de que o valor atribuído não é a própria função, mas sim o resultado da função que está sendo chamada.

Isso é semelhante ao conselho de Crockford sobre a capitalização das funções do construtor - serve como uma dica visual para qualquer pessoa que esteja olhando o código-fonte.

Bobby Eickhoff
fonte
Obrigado por apontar isso. Nunca encontrei uma maneira de me livrar da mensagem de aviso do JSLint "Tenha cuidado ao criar funções dentro de um loop." Fui cuidadoso e coloquei a função em um encerramento, mas o JSLint ainda reclamou. Agora eu sei que assumiu que usei o segundo padrão.
viam0Zah
Eu tenho feito isso "errado" todo esse tempo. E quando digo "todo esse tempo", escrevo JavaScript desde 1995.
Dave Land

Respostas:

73

Do guia de convenção de estilo de Douglass Crockford : (pesquise "invocado imediatamente")

Quando uma função deve ser invocada imediatamente, toda a expressão de invocação deve ser agrupada em parênteses para que fique claro que o valor que está sendo produzido é o resultado da função e não a própria função.

Então, basicamente, ele sente que torna mais clara a distinção entre os valores das funções e os valores das funções. Portanto, é uma questão estilística, não é realmente uma diferença substantiva no código em si.

referência atualizada, o PPT antigo não existe mais

cgp
fonte
1
Estou feliz por ter lido isso. Acabei de ler Javascript: as partes boas, e fiquei pensando que atribuir o resultado da chamada de uma função é uma sintaxe muito ruim, porque você precisa olhar a primeira e a última linhas para entender o que está acontecendo. Ele não usa os parênteses de embrulho no livro, mas vejo exatamente por que os recomenda.
Skilldrick
2
@altCognito, você pode fornecer um novo link para o PPT?
th1rdey3
1
Procurei
1
Não consegui encontrar o PPT original, mas consegui encontrar o mesmo ponto encontrado em seu guia de convenção javascript.
cgp
archive.org tem?
John Greene
2

Funções anônimas imediatamente chamadas são agrupadas em parênteses porque:

  1. Elas são expressões de função e deixar os parênteses de fora faria com que fossem interpretadas como uma declaração de função, o que é um erro de sintaxe.

  2. Expressões de função não podem começar com a palavra função.

  3. Ao atribuir a expressão de função a uma variável, a função em si não é retornada, o valor de retorno da função é retornado, portanto, os parênteses avaliam o que está dentro deles e produzem um valor.quando a função é executada e os parênteses posteriores ..}()fazem com que a função seja executada imediatamente.

Datã
fonte
Dathan, você está respondendo a uma pergunta diferente. Você está correto ao dizer que os parênteses às vezes são sintaticamente necessários para que o analisador possa distinguir expressões de função de declarações de função. Mas minha pergunta é sobre a colocação dos parênteses de invocação. Seu terceiro ponto é impreciso; os parênteses são desnecessários nesse caso.
Bobby Eickhoff
Eu estava respondendo ao seu primeiro exemplo em que a função imediatamente chamada anônima não foi atribuída a uma variável e, portanto, os parênteses são sintaticamente necessários pelos 2 primeiros motivos. A terceira razão foi apenas restabelecer o que você disse: "o parêntese de abertura dá uma indicação inicial de que o valor sendo atribuído não é a função em si, mas sim o resultado da função que está sendo chamada." Mas acho que não ficou claro.
Dathan
-3

Ou use:

void function () {
...
} ()
Agamemnus
fonte