Es funktioniert nicht, weil es als analysiert FunctionDeclaration
wird und die Namenskennung von Funktionsdeklarationen obligatorisch ist .
Wenn Sie es mit Klammern umgeben, wird es als a ausgewertet FunctionExpression
, und Funktionsausdrücke können benannt werden oder nicht.
Die Grammatik von a FunctionDeclaration
sieht so aus:
function Identifier ( FormalParameterListopt ) { FunctionBody }
Und FunctionExpression
s:
function Identifieropt ( FormalParameterListopt ) { FunctionBody }
Wie Sie sehen können, ist das Token Identifier
(Identifier opt ) FunctionExpression
optional, daher können wir einen Funktionsausdruck ohne definierten Namen haben:
(function () {
alert(2 + 2);
}());
Oder benannter Funktionsausdruck:
(function foo() {
alert(2 + 2);
}());
Die Klammern (formal als Gruppierungsoperator bezeichnet ) können nur Ausdrücke umgeben, und ein Funktionsausdruck wird ausgewertet.
Die beiden Grammatikproduktionen können mehrdeutig sein und genau gleich aussehen, zum Beispiel:
function foo () {} // FunctionDeclaration
0,function foo () {} // FunctionExpression
Der Parser weiß, ob es sich um ein FunctionDeclaration
oder ein handelt FunctionExpression
, je nachdem, in welchem Kontext es angezeigt wird.
Im obigen Beispiel ist der zweite ein Ausdruck, da der Komma-Operator auch nur Ausdrücke verarbeiten kann.
Andererseits FunctionDeclaration
könnte s tatsächlich nur im sogenannten " Program
" Code erscheinen, dh Code außerhalb des globalen Bereichs und innerhalb FunctionBody
anderer Funktionen.
Funktionen innerhalb von Blöcken sollten vermieden werden, da sie zu einem unvorhersehbaren Verhalten führen können, z.
if (true) {
function foo() {
alert('true');
}
} else {
function foo() {
alert('false!');
}
}
foo(); // true? false? why?
Der obige Code sollte tatsächlich a erzeugen SyntaxError
, da a Block
nur Anweisungen enthalten kann (und die ECMAScript-Spezifikation keine Funktionsanweisung definiert), die meisten Implementierungen jedoch tolerant sind und einfach die zweite Funktion übernehmen, die alarmiert 'false!'
.
Die Mozilla-Implementierungen - Nashorn, SpiderMonkey - haben ein anderes Verhalten. Ihre Grammatik enthält eine nicht standardmäßige Funktionsanweisung, was bedeutet, dass die Funktion bei bewertet wird Laufzeit und nicht zur Analysezeit wird, wie dies bei FunctionDeclaration
s der . In diesen Implementierungen wird die erste Funktion definiert.
Funktionen können auf verschiedene Arten deklariert werden. Vergleichen Sie Folgendes :
1- Eine Funktion, die mit dem der Variablen multiplizierten Funktionskonstruktor multipliziert wurde :
var multiply = new Function("x", "y", "return x * y;");
2- Eine Funktionsdeklaration einer Funktion namens multiplizieren :
function multiply(x, y) {
return x * y;
}
3- Ein der Variablen multiplizierter Funktionsausdruck multiplizieren :
var multiply = function (x, y) {
return x * y;
};
4- Ein benannter Funktionsausdruck func_name , der der Variablen multiplizieren zugewiesen ist :
var multiply = function func_name(x, y) {
return x * y;
};