Почему существует два разных синтаксиса для вызова выражений анонимных функций? - PullRequest
1 голос
/ 28 ноября 2010

Я только что прочитал статью Бена Алмана о выражениях с немедленным вызовом функций и удивился этой части, где он представляет выражения функций и замыкания (на самом деле еще не относящиеся к IIFE):

// ...doesn't it stand to reason that the function expression itself can
// be invoked, just by putting () after it?

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

// This works! Well, almost. A minor JavaScript syntax issue actually
// requires that ambiguity between function declarations and function
// expressions be eliminated, which can be done by wrapping the function
// expression in parens.

// The following pattern is used universally to create an anonymous
// closure with "privacy":

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

// This parens syntax is also valid (I prefer the previous version):

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

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

Был ли этот синтаксис сознательно введен только для вызова анонимных замыканий?Или это побочный продукт какого-то другого синтаксического свойства?

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

Кто-нибудь может сказать мне, что я здесь скучаю?

Ответы [ 2 ]

3 голосов
/ 28 ноября 2010

Все это происходит потому, что JavaScript имеет два контекста синтаксического анализа: выражение и оператор. Запись function foo() {} на уровне оператора определяет функцию foo в этой области, тогда как function foo() {} на уровне выражения оценивает новую анонимную функцию (которая может рекурсивно вызывать себя как foo).

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

Итак, запись (function() {}) заставляет синтаксический анализатор рассматривать функцию как выражение. Поскольку выражения могут содержать только другие выражения (без операторов), из этого также следует, что если вы напишите (something-that-contains function(){} and-other-stuff), то функция в ней все равно будет обрабатываться как выражение.

1 голос
/ 28 ноября 2010

Второе работает, потому что выражение в скобках не может быть интерпретировано как объявление функции (поэтому это должно быть выражение функции, решающее проблему неоднозначности с исходным первым выражением).

...