Это будет длинный ответ, но даст вам необходимый фон. В JavaScript существует два способа функция может быть определена: Определение функции (классический вид)
function foo() {
//why do we always use
}
, а затем более темный типа, выражение функции
var bar = function() {
//foo and bar
};
В сущности же самое происходит при исполнении. Создается функциональный объект, выделена память, а идентификатор привязан к этой функции. Разница заключается в синтаксисе. Первый сам является заявлением, которое объявляет новую функцию, последнее является выражением.
Выражение функции дает нам возможность вставить функцию в любое место, где ожидалось бы нормальное выражение. Это дает возможность анонимным функциям и обратным вызовам. Возьмем, например,
setTimeout(500, function() {
//for examples
});
Здесь анонимная функция будет выполняться всякий раз, когда это задает setTimeout. Однако, если мы хотим немедленно выполнить выражение функции, нам нужно убедиться, что синтаксис распознается как выражение, иначе мы имеем двусмысленность относительно того, не означает ли мы выражение функции или оператор.
var fourteen = function sumOfSquares() {
var value = 0;
for (var i = 0; i < 4; i++)
value += i * i;
return value;
}();
Здесь sumOfSquares
немедленно вызывается, поскольку он может быть признан в качестве выражения. fourteen
становится 14
и sumOfSquares - сборщик мусора. В вашем примере оператор группировки ()
принуждает его содержимое к выражению, поэтому функция является выражением и может быть вызвана немедленно как таковая.
Важно отметить, что разница между моим первым примером foo и bar - это подъем. Если вы не знаете, что это такое, вам следует сказать быстрый поиск Google или два, но быстрое и грязное определение заключается в том, что подъем является поведением JavaScript, чтобы принести объявления (переменные и функции) в начало области. Эти объявления обычно только поднимают идентификатор, но не его инициализированное значение, поэтому вся область видимости будет иметь возможность видеть переменную/функцию до того, как ей будет присвоено значение.
С определениями функций это не так, здесь вся декларация поднята и будет видна во всей области содержимого.
console.log("lose your " + function() {
fiz(); //will execute fiz
buzz(); //throws TypeError
function fiz() {
console.log("lose your scoping,");
}
var buzz = function() {
console.log("and win forever");
};
return "sanity";
}()); //prints "lose your scoping, lose your sanity"
Одним словом: двусмысленность. Я не помню точные термины, но 'function() {...}' является объявлением, а '(function() {...})' является выражением, выражение, вызываемое значением '()' работает. –
FYI, это также работает ~ '+ function() {...}()' as does!! Function() {...}() ' – Phil
Один из функций, которые интерпретатор оценивает. Другое - это определение функции, которое интерпретатор просто добавляет определение функции в текущую область. Параны превращают его в выражение функции, которое вы хотите. Почему он работает таким образом из-за деталей языковой грамматики. – jfriend00