Почему скобки необходимы вокруг JavaScript IIFE? [дубликат]
этот вопрос уже есть ответ здесь:
Я читаю на JavaScript IIFE и до сих пор понимаю концепцию, но мне интересно о внешней скобке. В частности, почему они необходимы? Для пример,
(function() {var msg='I love JavaScript'; console.log(msg);}());
работает, а
function() {var msg='I love JavaScript'; console.log(msg);}();
генерирует синтаксическую ошибку. Почему? Есть много дискуссий по IIFE, но я не вижу четкого объяснения того, почему требуются круглые скобки.
3 ответов
версия IIFE, которая заключена в скобки, работает, потому что это отмечает объявление объявления внутренней функции как выражение.
http://benalman.com/news/2010/11/immediately-invoked-function-expression/
для более подробного объяснения см.:
расширенный JavaScript: почему эта функция заключена в круглые скобки?
подсказка:
ссылка оператор (()) работает только с выражениями, а не с объявлениями.
существует два способа создания функций в JavaScript (ну, 3, но давайте проигнорируем new Function()
). Вы можете либо написать объявление функции, либо написать выражение функции.
объявление функции само по себе является оператором, и операторы сами по себе не возвращают значения (давайте также проигнорируем, как консоль отладки или узел.js REPL печать возвращаемых значений операторов). Однако выражение функции является правильным выражением и выражениями в JavaScript возвращает значения, которые можно использовать немедленно.
теперь вы, возможно, видели людей, говорящих, что следующее выражение функции:
var x = function () {};
может возникнуть соблазн заключить, что синтаксис:
function () {};
это то, что делает это выражение. Но это неправильно. Синтаксис выше-это то, что делает его анонимной функцией. Анонимные функции могут быть объявлением или выражением. Что делает это выражение это синтаксис:
var x = ...
то есть, все, что справа от =
знак-это выражение. Выражения облегчают написание математических формул на языках программирования. Таким образом, в целом везде, где ожидается обработка математики, является выражением.
некоторые из форм выражений в JavaScript включают:
- Все права
=
оператор - вещи в скобки
()
это не вызов функции брекеты - все справа от математического оператора (
+
,-
,*
,/
) - все аргументы троичного оператора
.. ? .. : ..
когда вы пишете:
function () {}
это объявление и не возвращает значение (заявленные функции). Поэтому попытка вызвать не-результат является ошибкой.
но когда вы пишете:
(function () {})
это выражение и возвращает значение ( объявленная функция), которая может быть использована немедленно (например, может быть вызвана или назначена).
обратите внимание на правила для того, что считается выше выражений. Из этого следует, что скобки-это не единственные вещи, которые вы можете использовать для создания IIFE. Ниже приведены допустимые способы построения IIFEs (поскольку мы пишем выражения функций):
tmp=function(){}()
+function(){}()
-function(){}()
0/function(){}()
0*function(){}()
0?0:function(){}()
(function(){}())
(function(){})()
вы можете увидеть один из вышеперечисленных нестандартных форм (в частности,+
версия) в третьей стороне библиотеки, потому что они хотят сохранить один байт. Но я настоятельно рекомендую вам использовать только формы скобок (либо хорошо), потому что они широко признаны другими программистами как IIFEs.
это будет многословный ответ, но даст вам необходимый фон. В 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 будет собран "мусор". в вашем примере оператор группировки ()
coerces свое содержание в выражение, поэтому функция выражение и может быть вызвана немедленно как такие.
одна важная вещь, чтобы отметить разницу между моим первым примером 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"