Cela ne fonctionne pas car il est analysé comme un FunctionDeclaration
, et l'identifiant de nom des déclarations de fonction est obligatoire .
Lorsque vous l'entourez de parenthèses, il est évalué comme un FunctionExpression
, et les expressions de fonction peuvent être nommées ou non.
La grammaire d'un FunctionDeclaration
ressemble à ceci:
function Identifier ( FormalParameterListopt ) { FunctionBody }
Et FunctionExpression
s:
function Identifieropt ( FormalParameterListopt ) { FunctionBody }
Comme vous pouvez le voir, le jeton Identifier
(Identifier opt ) FunctionExpression
est facultatif, nous pouvons donc avoir une expression de fonction sans nom défini:
(function () {
alert(2 + 2);
}());
Ou expression de fonction nommée :
(function foo() {
alert(2 + 2);
}());
Les parenthèses (officiellement appelé l'opérateur de regroupement ) ne peuvent entourer que les expressions et une expression de fonction est évaluée.
Les deux productions grammaticales peuvent être ambiguës, et elles peuvent être exactement identiques, par exemple:
function foo () {} // FunctionDeclaration
0,function foo () {} // FunctionExpression
L'analyseur sait si c'est un FunctionDeclaration
ou un FunctionExpression
, selon le contexte où il apparaît.
Dans l'exemple ci-dessus, le second est une expression car l' opérateur Virgule peut également gérer uniquement les expressions.
D'un autre côté, les FunctionDeclaration
s ne peuvent en fait apparaître que dans ce qu'on appelle le Program
code " ", ce qui signifie du code à l'extérieur dans la portée globale et à l'intérieur FunctionBody
des autres fonctions.
Les fonctions à l'intérieur des blocs doivent être évitées, car elles peuvent entraîner un comportement imprévisible, par exemple:
if (true) {
function foo() {
alert('true');
}
} else {
function foo() {
alert('false!');
}
}
foo(); // true? false? why?
Le code ci-dessus devrait en fait produire un SyntaxError
, car a Block
ne peut contenir que des instructions (et la spécification ECMAScript ne définit aucune instruction de fonction), mais la plupart des implémentations sont tolérantes et prendront simplement la deuxième fonction, celle qui alerte 'false!'
.
Les implémentations de Mozilla -Rhino, SpiderMonkey, - ont un comportement différent. Leur grammaire contient un énoncé de fonction non standard , ce qui signifie que la fonction sera évaluée au moment de l' exécution , et non au moment de l'analyse, comme cela se produit avec FunctionDeclaration
s. Dans ces implémentations, nous obtiendrons la première fonction définie.
Les fonctions peuvent être déclarées de différentes manières, comparez les éléments suivants :
1- Une fonction définie avec le constructeur Function affecté à la variable multiply :
var multiply = new Function("x", "y", "return x * y;");
2- Une déclaration de fonction d'une fonction nommée multiplier :
function multiply(x, y) {
return x * y;
}
3- Une expression de fonction affectée à la variable multiplier :
var multiply = function (x, y) {
return x * y;
};
4- Une expression de fonction nommée func_name , affectée à la variable multiplier :
var multiply = function func_name(x, y) {
return x * y;
};