Расположение скобок для автоматического выполнения анонимных функций JavaScript?
Недавно я сравнивал текущую версию json2.js с версией, которую я имел в своем проекте, и заметил разницу в том, как выражение функции было создано и выполнено самостоятельно.
Код, используемый для переноса анонимной функции в круглые скобки и последующего ее выполнения,
(function () {
// code here
})();
но теперь он переносит автоматически выполняемую функцию в круглые скобки.
(function () {
// code here
}());
В принятом ответе инкапсулированного синтаксиса анонимной функции JavaScript Explain есть комментарий, который "оба: (function(){})();
а также (function(){}());
действительны ".
Мне было интересно, в чем разница? Занимает ли первое место память, оставляя вокруг глобальную анонимную функцию? Где должна находиться скобка?
4 ответа
Они практически одинаковы.
Первый заключает скобки в скобки вокруг функции, чтобы сделать ее допустимым выражением, и вызывает ее. Результат выражения не определен.
Вторая выполняет функцию, а круглые скобки вокруг автоматического вызова делают ее допустимым выражением. Он также оценивается как неопределенный.
Я не думаю, что есть "правильный" способ сделать это, так как результат выражения одинаков.
> function(){}()
SyntaxError: Unexpected token (
> (function(){})()
undefined
> (function(){return 'foo'})()
"foo"
> (function(){ return 'foo'}())
"foo"
В этом случае это не имеет значения. Вы вызываете выражение, которое разрешается для функции в первом определении, и определяете и немедленно вызываете функцию во втором примере. Они похожи, потому что выражение функции в первом примере - это просто определение функции.
Есть и другие, более очевидные, полезные случаи для вызова выражений, которые разрешают функции:
(foo || bar)()
Там нет никакой разницы, кроме синтаксиса.
Что касается ваших опасений по поводу второго способа сделать это:
Рассматривать:
(function namedfunc () { ... }())
namedfunc
все равно не будет в глобальной области, даже если вы указали имя. То же самое касается анонимных функций. Единственный способ получить его в этой области - это присвоить его переменной внутри скобок.
((namedfunc = function namedfunc () { ... })())
Внешние паренсы не нужны:
(namedfunc = function namedfunc () { ... })()
Но вы все равно не хотели эту глобальную декларацию?
Так что это сводится к:
(function namedfunc () { ... })()
И вы можете уменьшить его еще больше: имя не нужно, поскольку оно никогда не будет использоваться (если ваша функция не является рекурсивной... и даже тогда вы можете использовать arguments.callee
)
(function () { ... })()
Вот как я об этом думаю (может быть неправильно, я еще не читал спецификацию ECMAScript). Надеюсь, поможет.
Разница существует только потому, что Дугласу Крокфорду не нравится первый стиль для IIFE! (серьезно) Как вы можете видеть в этом видео!,
Единственная причина существования дополнительной упаковки ()
{в обоих стилях} должен помочь сделать этот раздел кода Выражение функции, потому что объявление функции не может быть вызвано немедленно. Некоторые скрипты / миниферы просто используют +
, !
, -
& ~
вместо слишком круглых скобок. Как это:
+function() {
var foo = 'bar';
}();
!function() {
var foo = 'bar';
}();
-function() {
var foo = 'bar';
}();
~function() {
var foo = 'bar';
}();
И все это точно так же, как ваши альтернативы. Выбор среди этих случаев полностью за вами и не имеет значения. {Те, с ()
создайте файл на 1 байт больше;-) }