Расположение скобок для автоматического выполнения анонимных функций JavaScript? - PullRequest
102 голосов
/ 02 августа 2010

Я недавно сравнивал текущую версию json2.js с версией, которую я имел в своем проекте, и заметил разницу в том, как было создано и выполнено выражение функции.

Код, используемый для переноса анонимной функции в круглые скобки и последующего ее выполнения,

(function () {
  // code here
})();

, но теперь она включает в себя автоматически выполняемую функцию в скобках.

(function () {
  // code here
}());

В принятом ответе есть комментарий от CMS * Объясните синтаксис анонимной функции JavaScript , что «оба: (function(){})(); и (function(){}()); допустимы».

Мне было интересно, в чем разница? Занимает ли первое место память, оставляя вокруг глобальную анонимную функцию? Где должна находиться скобка?

Ответы [ 4 ]

62 голосов
/ 02 августа 2010

Они практически одинаковы.

Первый оборачивает скобки вокруг функции, чтобы сделать ее допустимым выражением, и вызывает ее. Результат выражения не определен.

Вторая выполняет функцию, а круглые скобки вокруг автоматического вызова делают ее допустимым выражением. Он также оценивается как неопределенный.

Я не думаю, что есть "правильный" способ сделать это, так как результат выражения один и тот же.

> function(){}()
SyntaxError: Unexpected token (
> (function(){})()
undefined
> (function(){return 'foo'})()
"foo"
> (function(){ return 'foo'}())
"foo"
13 голосов
/ 02 августа 2010

В таком случае это не имеет значения.Вы вызываете выражение, которое разрешается для функции в первом определении, и определяете и немедленно вызываете функцию во втором примере.Они похожи, потому что выражение функции в первом примере - это просто определение функции.

Существуют и другие, более очевидно, полезные случаи для вызова выражений, которые разрешают функции:

8 голосов
/ 02 августа 2010

Нет никакой разницы, кроме синтаксиса.

Что касается вашего беспокойства по поводу второго способа сделать это:

Рассмотрим:

(function namedfunc () { ... }())

namedfunc все равно не будет находиться в глобальной области действия, даже если вы указали имя.То же самое касается анонимных функций.Единственный способ получить его в этой области - это присвоить его переменной внутри паренов.

((namedfunc = function namedfunc () { ... })())

Внешние парены не нужны:

(namedfunc = function namedfunc () { ... })()

Но вы этого не сделалиВ любом случае, хотите ли вы это глобальное объявление?

Итак, оно сводится к:

(function namedfunc () { ... })()

И вы можете уменьшить его еще больше: имя не нужно, поскольку оно никогда не будет использоваться (если ваша функция не является рекурсивной ... и даже тогда вы можете использовать arguments.callee)

(function () { ... })()

Я так об этом думаю (может быть, это неправильно, я еще не читал спецификацию ECMAScript).Надеюсь, это поможет.

0 голосов
/ 24 февраля 2017

Разница существует только потому, что Дугласу Крокфорду не нравится первый стиль для IIFEs ! (серьезно) Как вы можете видеть в этом видео !! .

Единственная причина существования дополнительного переноса () {в обоих стилях} состоит в том, чтобы помочь создать этот фрагмент кода Выражение функции , поскольку Объявление функции не может быть немедленно называется. Некоторые скрипты / минимизаторы просто используют +, !, - & ~ вместо слишком круглых скобок. Как это:

+function() {  
    var foo = 'bar';  
}();

!function() {  
    var foo = 'bar';  
}();

-function() {  
    var foo = 'bar';  
}();

~function() {  
    var foo = 'bar';  
}();

И все это точно так же, как ваши альтернативы. Выбор среди этих случаев полностью за вами и не имеет значения. {Те с () производят 1 байт большего файла ;-)}

...