Расположение скобок для автоматического выполнения анонимных функций 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 байт больше;-) }

Другие вопросы по тегам