Não funciona porque está sendo analisado como ae FunctionDeclaration
o identificador de nome das declarações de função é obrigatório .
Quando você o coloca entre parênteses, ele é avaliado como FunctionExpression
ae as expressões de função podem ser nomeadas ou não.
A gramática de a FunctionDeclaration
é assim:
function Identifier ( FormalParameterListopt ) { FunctionBody }
E FunctionExpression
s:
function Identifieropt ( FormalParameterListopt ) { FunctionBody }
Como você pode ver, o token Identifier
(Identifier opt ) FunctionExpression
é opcional, portanto, podemos ter uma expressão de função sem um nome definido:
(function () {
alert(2 + 2);
}());
Ou expressão da função nomeada :
(function foo() {
alert(2 + 2);
}());
Os parênteses (formalmente chamado de operador de agrupamento ) podem envolver apenas expressões e uma expressão de função é avaliada.
As duas produções gramaticais podem ser ambíguas e podem parecer exatamente iguais, por exemplo:
function foo () {} // FunctionDeclaration
0,function foo () {} // FunctionExpression
O analisador sabe se é um FunctionDeclaration
ou um FunctionExpression
, dependendo do contexto em que aparece.
No exemplo acima, o segundo é uma expressão porque o operador Vírgula também pode manipular apenas expressões.
Por outro lado, FunctionDeclaration
s poderia aparecer apenas no Program
código " ", significando código fora do escopo global e dentro FunctionBody
de outras funções.
As funções dentro dos blocos devem ser evitadas, pois podem levar a um comportamento imprevisível, por exemplo:
if (true) {
function foo() {
alert('true');
}
} else {
function foo() {
alert('false!');
}
}
foo(); // true? false? why?
O código acima deve realmente produzir a SyntaxError
, uma vez que a Block
pode conter apenas instruções (e a especificação ECMAScript não define nenhuma instrução de função), mas a maioria das implementações é tolerante e simplesmente aceita a segunda função, a que alerta 'false!'
.
As implementações do Mozilla - Rhino, SpiderMonkey, - têm um comportamento diferente. Sua gramática contém uma Declaração de Função não padrão , o que significa que a função será avaliada no tempo de execução , não no tempo de análise, como acontece com FunctionDeclaration
s. Nessas implementações, obteremos a primeira função definida.
As funções podem ser declaradas de diferentes maneiras; compare o seguinte :
1- Uma função definida com o construtor Function atribuído à variável multiplica :
var multiply = new Function("x", "y", "return x * y;");
2- Uma declaração de função de uma função denominada multiply :
function multiply(x, y) {
return x * y;
}
3- Uma expressão de função atribuída à variável multiplica :
var multiply = function (x, y) {
return x * y;
};
4- Uma expressão de função nomeada func_name , atribuída à variável multiply :
var multiply = function func_name(x, y) {
return x * y;
};