Non funziona perché viene analizzato come a FunctionDeclaration
e l'identificatore del nome delle dichiarazioni di funzione è obbligatorio .
Quando lo circondi tra parentesi, viene valutato come un FunctionExpression
e le espressioni di funzione possono essere nominate o meno.
La grammatica di un FunctionDeclaration
assomiglia a questo:
function Identifier ( FormalParameterListopt ) { FunctionBody }
E FunctionExpression
s:
function Identifieropt ( FormalParameterListopt ) { FunctionBody }
Come puoi vedere l' opzioneIdentifier
(Identificatore opt token ) in FunctionExpression
è facoltativo, quindi possiamo avere un'espressione di funzione senza un nome definito:
(function () {
alert(2 + 2);
}());
O espressione di funzione denominata :
(function foo() {
alert(2 + 2);
}());
Le parentesi (formalmente denominate Operatore di raggruppamento ) possono racchiudere solo espressioni e viene valutata un'espressione di funzione.
Le due produzioni grammaticali possono essere ambigue e possono apparire esattamente uguali, ad esempio:
function foo () {} // FunctionDeclaration
0,function foo () {} // FunctionExpression
Il parser sa se è a FunctionDeclaration
o a FunctionExpression
, a seconda del contesto in cui appare.
Nell'esempio sopra, il secondo è un'espressione perché l' operatore Comma può anche gestire solo espressioni.
D'altra parte, FunctionDeclaration
s potrebbe effettivamente apparire solo nel cosiddetto Program
codice " ", che significa codice all'esterno nell'ambito globale e all'interno FunctionBody
delle altre funzioni.
Le funzioni all'interno dei blocchi dovrebbero essere evitate, perché possono condurre un comportamento imprevedibile, ad esempio:
if (true) {
function foo() {
alert('true');
}
} else {
function foo() {
alert('false!');
}
}
foo(); // true? false? why?
Il codice sopra dovrebbe effettivamente produrre un SyntaxError
, poiché un Block
può contenere solo istruzioni (e la specifica ECMAScript non definisce alcuna istruzione di funzione), ma la maggior parte delle implementazioni sono tolleranti e prenderanno semplicemente la seconda funzione, quella che avvisa'false!'
.
Le implementazioni di Mozilla - Rhino, SpiderMonkey - hanno un comportamento diverso. La loro grammatica contiene un'istruzione di funzione non standard , il che significa che la funzione verrà valutata in fase di esecuzione , non al momento dell'analisi, come accade con FunctionDeclaration
s. In queste implementazioni otterremo la prima funzione definita.
Le funzioni possono essere dichiarate in diversi modi, confrontare quanto segue :
1- Una funzione definita con il costruttore Funzione assegnata alla variabile si moltiplica :
var multiply = new Function("x", "y", "return x * y;");
2- Una dichiarazione di funzione di una funzione chiamata moltiplica :
function multiply(x, y) {
return x * y;
}
3- Un'espressione di funzione assegnata alla variabile si moltiplica :
var multiply = function (x, y) {
return x * y;
};
4- Un'espressione di funzione nominata nome_funzione , assegnata alla variabile moltiplicare :
var multiply = function func_name(x, y) {
return x * y;
};