ES6 немедленно вызвал функцию стрелки

Почему это работает в консоли Node.js (протестировано в 4.1.1 и 5.3.0), но не работает в браузере (проверено в Chrome)? Этот блок кода должен создавать и вызывать анонимную функцию, которая регистрирует Ok.

() => {
  console.log('Ok');
}()

Кроме того, хотя выше работает в Node, это не работает:

n => {
  console.log('Ok');
}()

И это:

(n) => {
  console.log('Ok');
}()

Нечетным является то, что при добавлении параметра он фактически выдает SyntaxError в вызывающей немедленно части.

Ответ 1

Вам нужно сделать это выражением функции вместо определения функции, которая не нуждается в имени и делает его действительным JavaScript.

(() => {
  console.log('Ok');
})()

Является эквивалентом IIFE

(function(){
   console.log('Ok')
})();

И возможная причина, по которой это работает в Node.js, но не в хроме, состоит в том, что его синтаксический анализатор интерпретирует его как функцию самоисполнения, поскольку этот

function() { console.log('hello'); }();

отлично работает в Node.js Это выражение функции, chrome и firefox, и большинство браузеров интерпретирует его таким образом. Вам нужно вызвать его вручную.

Самый распространенный способ сказать парсеру ожидать выражения функции - просто обернуть его в parens, потому что в JavaScript парс не может содержать операторов. В этот момент, когда синтаксический анализатор встречает ключевое слово function, он разбирается в нем как выражение функции, а не объявление функции.

Что касается параметризованной версии, это будет работать.

((n) => {
  console.log('Ok');
})()

Ответ 2

Ни одно из них не должно работать без круглых скобок.

Почему?

Потому что согласно спецификации:

Таким образом, функция ArrowFunction не может находиться в LHS вызывного вызова.


То, что это эффективно означает, как следует интерпретировать =>, заключается в том, что он работает на том же уровне, что и операторы присваивания =, += и т.д.

Значение

  • x => {foo}() не становится (x => {foo})()
  • Интерпретатор пытается интерпретировать его как x => ({foo}())
  • Таким образом, это все еще SyntaxError
  • Таким образом, интерпретатор решает, что (, должно быть, был неправильным и выбрасывает SyntaxError

Здесь была проблема с Babel об этом здесь.

Ответ 3

Причина, по которой вы видите такие проблемы, заключается в том, что сама консоль пытается эмулировать глобальную область контекста, на который вы сейчас нацеливаете. Он также пытается захватить возвращаемые значения из операторов и выражений, которые вы пишете на консоли, чтобы они отображались как результаты. Возьмем, например:

> 3 + 2
< 5

Здесь он выполняется так, как если бы это было выражение, но вы написали его, как будто это было утверждение. В обычных сценариях значение будет отбрасываться, но здесь код должен быть внутренне искажен (например, обертывание всего оператора контекстом функции и инструкцией return), которая вызывает всевозможные странные эффекты, в том числе проблемы, re experience.

Это также одна из причин, почему некоторый открытый код ES6 в скриптах работает нормально, но не в консоли Chrome Dev Tools.

Попробуйте выполнить это в Node и консоли Chrome:

{ let a = 3 }

В теге Node или <script> он работает нормально, но в консоли он дает Uncaught SyntaxError: Unexpected identifier. Он также дает вам ссылку на источник в форме VMxxx:1, которую вы можете щелкнуть, чтобы проверить оцениваемый источник, который отображается как:

({ let a = 3 })

Так зачем это делал?

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

Консоль пытается исправить эти случаи краев, будучи умными в отношении кода, но это выходит за рамки этого ответа, я думаю. Вы можете указать ошибку, чтобы убедиться, что это будет исправлено.

Вот хороший пример чего-то очень похожего:

fooobar.com/info/61745/...

Самый безопасный способ заставить ваш код работать, чтобы убедиться, что он может быть запущен как выражение и проверить исходную ссылку SyntaxError, чтобы узнать, что представляет собой фактический код выполнения, и реконструировать решение из этого. Обычно это означает пару стратегически расположенных круглых скобок.

Вкратце: консоль пытается как можно точнее эмулировать глобальный контекст выполнения, но из-за ограничений взаимодействия с движком v8 и семантикой JavaScript это иногда трудно или невозможно решить.