Nie działa, ponieważ jest analizowany jako a FunctionDeclaration
, a identyfikator nazwy deklaracji funkcji jest obowiązkowy .
Gdy otaczasz go nawiasami, jest on oceniany jako a FunctionExpression
, a wyrażenia funkcyjne można nazwać lub nie.
Gramatyka FunctionDeclaration
wygląda następująco:
function Identifier ( FormalParameterListopt ) { FunctionBody }
I FunctionExpression
s:
function Identifieropt ( FormalParameterListopt ) { FunctionBody }
Jak widać token Identifier
(Identyfikator opt ) FunctionExpression
jest opcjonalny, dlatego możemy mieć wyrażenie funkcyjne bez zdefiniowanej nazwy:
(function () {
alert(2 + 2);
}());
Lub nazwane wyrażenie funkcji:
(function foo() {
alert(2 + 2);
}());
Nawiasy (formalnie nazywane operatorem grupowania ) mogą otaczać tylko wyrażenia, a wyrażenie funkcji jest oceniane.
Dwie produkcje gramatyczne mogą być niejednoznaczne i mogą wyglądać dokładnie tak samo, na przykład:
function foo () {} // FunctionDeclaration
0,function foo () {} // FunctionExpression
Analizator składni wie, czy jest to a FunctionDeclaration
lub a FunctionExpression
, w zależności od kontekstu, w którym się pojawia.
W powyższym przykładzie drugi jest wyrażeniem, ponieważ operator przecinka może również obsługiwać tylko wyrażenia.
Z drugiej strony, FunctionDeclaration
mogą faktycznie występować tylko w tak zwanym Program
kodzie, co oznacza kod poza zakresem globalnym i wewnątrz FunctionBody
innych funkcji.
Należy unikać funkcji wewnątrz bloków, ponieważ mogą one prowadzić do nieprzewidzianych zachowań, np .:
if (true) {
function foo() {
alert('true');
}
} else {
function foo() {
alert('false!');
}
}
foo(); // true? false? why?
Powyższy kod powinien faktycznie wygenerować SyntaxError
, ponieważ a Block
może zawierać tylko instrukcje (a Specyfikacja ECMAScript nie definiuje żadnej instrukcji funkcji), ale większość implementacji jest tolerancyjna i po prostu przyjmuje drugą funkcję, tę, która zaalarmuje 'false!'
.
Implementacje Mozilli - Rhino, SpiderMonkey - mają inne zachowanie. Ich gramatyka zawiera niestandardowe instrukcję funkcji, co oznacza, że funkcja będzie oceniana w czasie wykonywania , a nie w czasie analizy, jak to ma miejsce w przypadku FunctionDeclaration
s. W tych implementacjach zdefiniujemy pierwszą funkcję.
Funkcje można zadeklarować na różne sposoby, porównaj następujące :
1- Funkcja zdefiniowana za pomocą konstruktora funkcji przypisanego do zmiennej zwielokrotnia :
var multiply = new Function("x", "y", "return x * y;");
2- Deklaracja funkcji o nazwie mnożącej się :
function multiply(x, y) {
return x * y;
}
3- Wyrażenie funkcyjne przypisane do zmiennej zwielokrotnia się :
var multiply = function (x, y) {
return x * y;
};
4- Nazwane wyrażenie funkcyjne func_name , przypisane do zmiennej pomnóż :
var multiply = function func_name(x, y) {
return x * y;
};