Синтаксис немедленного вызова функции

110

Существует опция JSLint , фактически одна из хороших частей, которая «[требует] скобок вокруг немедленных вызовов», что означает, что конструкция

(function () {

  // ...

})();

вместо этого нужно было бы записать как

(function () {

  // ...

}());

У меня такой вопрос - может ли кто-нибудь объяснить, почему эту вторую форму можно считать лучше? Он более устойчивый? Менее подвержены ошибкам? Какое у него преимущество перед первой формой?


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

var someVar = (function () {

  // ...

}());

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

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

Бобби Айкхофф
источник
Спасибо за указание на это. Я так и не нашел способа избавиться от предупреждающего сообщения JSLint «Будьте осторожны при создании функций внутри цикла». Я был осторожен и закрыл функцию, но JSLint все еще жаловался. Теперь я знаю, что предполагалось, что я использовал второй шаблон.
viam0Zah 02
Все это время я делал это «неправильно». И когда я говорю «все это время», я пишу JavaScript с 1995 года.
Дэйв Лэнд

Ответы:

73

Из руководства по соглашению о стилях Дугласа Крокфорда : (ищите «вызывается немедленно»)

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

В общем, он считает, что это проясняет различие между значениями функций и значениями функций. Так что это стилистический вопрос, а не существенная разница в самом коде.

обновленная ссылка, старый PPT больше не существует

cgp
источник
1
Я рад, что прочитал это. Я только что закончил читать Javascript: The Good Parts, и я все время думал, что назначение результата вызова функции - это действительно плохой синтаксис, потому что вам нужно посмотреть на первую и последнюю строки, чтобы понять, что происходит. Он не использует в книге обертки, но я точно понимаю, почему он их рекомендует.
Skilldrick
2
@altCognito, можешь дать свежую ссылку на PPT?
th1rdey3
1
Я поискал в сети, но все еще не могу найти копию этого PPT
Forethinker
1
Мне не удалось найти оригинальный PPT, но я смог найти ту же точку, что и в его руководстве по соглашению о javascript.
cgp
archive.org есть?
Джон Грин
2

Сразу вызываемые анонимные функции заключают его в скобки, потому что:

  1. Это функциональные выражения, и если оставить скобки без скобок, это приведет к интерпретации объявления функции, что является синтаксической ошибкой.

  2. Функциональные выражения не могут начинаться со слова function.

  3. При присвоении выражения функции переменной сама функция не возвращается, возвращается возвращаемое значение функции, следовательно, скобки оценивают, что внутри них, и выдают значение.когда функция выполняется, а конечные скобки ..}()вызывают немедленное выполнение функции.

Дафан
источник
Дафан, вы отвечаете на другой вопрос. Вы правы, заключительные круглые скобки иногда необходимы синтаксически, чтобы синтаксический анализатор мог отличить выражения функций от объявлений функций. Но мой вопрос касается размещения скобок вызова. Ваш третий пункт неточен; заключительные круглые скобки в этом случае не нужны.
Бобби Айкхофф
Я отвечал на ваш первый пример, когда немедленно вызываемая анонимная функция не была назначена переменной, и поэтому круглые скобки синтаксически необходимы по первым двум причинам. Третья причина заключалась в том, чтобы просто восстановить то, что вы даже сказали: «открывающая скобка дает предварительное указание на то, что назначаемое значение не является самой функцией, а скорее результатом вызываемой функции». Но я думаю, это было непонятно.
Dathan
-3

Или используйте:

void function () {
...
} ()
Agamemnus
источник