Він не працює, тому що він розбирається як a FunctionDeclaration
, а ідентифікатор імен оголошень функції є обов'язковим .
Коли ви оточуєте його круглими дужками, він оцінюється як a FunctionExpression
, а вирази функцій можуть бути названі чи ні.
Граматика FunctionDeclaration
виглядає приблизно так:
function Identifier ( FormalParameterListopt ) { FunctionBody }
І FunctionExpression
s:
function Identifieropt ( FormalParameterListopt ) { FunctionBody }
Як ви бачите, що маркер Identifier
(ідентифікатор opt ) не FunctionExpression
є обов'язковим, тому ми можемо мати вираз функції без визначеного імені:
(function () {
alert(2 + 2);
}());
Або названий вираз функції:
(function foo() {
alert(2 + 2);
}());
Паретки (формально називаються оператором групування ) можуть оточувати лише вирази, і виражається функція.
Дві граматичні постановки можуть бути неоднозначними, і вони можуть виглядати абсолютно однаково, наприклад:
function foo () {} // FunctionDeclaration
0,function foo () {} // FunctionExpression
Аналізатор знає, чи це a, FunctionDeclaration
або a FunctionExpression
, залежно від контексту, де він з'являється.
У наведеному вище прикладі другий - це вираз, оскільки оператор Comma також може обробляти лише вирази.
З іншого боку, FunctionDeclaration
s насправді може з'являтися лише у тому, що називається Program
кодом, тобто кодом, який знаходиться зовні в глобальному масштабі та всередині FunctionBody
інших функцій.
Функцій всередині блоків слід уникати, оскільки вони можуть вести непередбачувану поведінку, наприклад:
if (true) {
function foo() {
alert('true');
}
} else {
function foo() {
alert('false!');
}
}
foo(); // true? false? why?
Наведений вище код насправді повинен створювати SyntaxError
, оскільки Block
може містити лише заяви (а специфікація ECMAScript не визначає жодного оператора функції), але більшість реалізацій є терпимими і просто приймуть другу функцію, ту, що попереджає 'false!'
.
Реалізації Mozilla -Rhino, SpiderMonkey, - відрізняються поведінкою. Їх граматика містить нестандартний виклад функції, що означає, що функція буде оцінена в час виконання , а не під час розбору, як це відбувається з FunctionDeclaration
s. У цих реалізаціях ми визначимо першу функцію.
Функції можна оголосити різними способами, порівняйте наступне :
1- Функція, визначена конструктором функцій, присвоєним змінній множити :
var multiply = new Function("x", "y", "return x * y;");
2- Оголошення функції функції, названої помножити :
function multiply(x, y) {
return x * y;
}
3- Вираз функції, присвоєне змінній множитися :
var multiply = function (x, y) {
return x * y;
};
4- Іменне вираження функції func_name , присвоєне змінній помножити :
var multiply = function func_name(x, y) {
return x * y;
};