ES6立即调用了箭头功能

时间:2016-01-04 10:53:00

标签: javascript node.js arrow-functions

为什么这在Node.js控制台中运行(在4.1.1和5.3.0中测试过)但在浏览器中不起作用(在Chrome中测试过)?此代码块应创建并调用记录Ok

的匿名函数
() => {
  console.log('Ok');
}()

此外,虽然Node中的上述工作,但这不起作用:

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

也不是这样:

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

奇怪的是,当添加参数时,它实际上会在立即调用的部分抛出SyntaxError

4 个答案:

答案 0 :(得分:137)

您需要将其设为函数表达式,而不是函数定义,它不需要名称并使其成为有效的JavaScript。

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

相当于IIFE

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

这可能是因为它在Node.js中而不是在chrome中工作的原因是因为它的解析器将它解释为一个自执行函数,因为这个

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

Node.js中正常工作这是一个函数表达式,chrome和firefox,大多数浏览器都是这样解释它的。您需要手动调用它。

告诉解析器期望函数表达式的最广泛接受的方法就是将它包装在parens中,因为在JavaScript中,parens不能包含语句。此时,当解析器遇到function关键字时,它知道将其解析为函数表达式而不是函数声明。

关于参数化版本,这将有效。

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

答案 1 :(得分:17)

如果没有括号,这些都不适用。

为什么?

因为根据规范:

  1. ArrowFunction listed under AssignmentExpression
  2. LHS of a CallExpression必须是 MemberExpression SuperCall CallExpression
  3. 所以 ArrowFunction 不能出现在 CallExpression 的LHS上。

    这对=>应该如何解释有效的意义在于,它与赋值运算符=+=等处于同一级别。

    <击>含义

    <击>
      <击>
    • x => {foo}() 成为(x => {foo})()
    • 解释器尝试将其解释为x => ({foo}())
    • 因此它仍然是 SyntaxError
    • 所以解释器决定(一定是错的并抛出 SyntaxError

    Babel上也有一个关于它的错误here

答案 2 :(得分:2)

您遇到此类问题的原因是控制台本身会尝试模拟您当前定位的上下文的全局范围。它还尝试从您在控制台中编写的语句和表达式中捕获返回值,以便显示为结果。举个例子:

> 3 + 2
< 5

在这里,它就像表达式一样执行,但你已经把它写成了一个声明。在普通的脚本中,值将被丢弃,但在这里,代码必须在内部被破坏(比如用函数上下文和return语句包装整个语句),这会导致各种奇怪的效果,包括问题你经历过。

这也是为什么脚本中的一些裸ES6代码工作正常但在Chrome Dev Tools控制台中没有的原因之一。

尝试在Node和Chrome控制台中执行此操作:

{ let a = 3 }

在Node或<script>标记中,它可以正常工作,但在控制台中,它会提供Uncaught SyntaxError: Unexpected identifier。它还以VMxxx:1的形式为您提供了源的链接,您可以单击该链接以检查评估的源,该源显示为:

({ let a = 3 })

那为什么要这样做?

答案是它需要将代码转换为表达式,以便将结果返回给调用者并显示在控制台中。你可以通过将语句包装在括号中来实现这一点,这使得它成为一个表达式,但它也使语句在句法上不正确(表达式不能有块声明)。

控制台确实试图通过对代码的智能来修复这些边缘情况,但我认为这超出了这个答案的范围。你可以提交一个错误,看看他们是否考虑修复这些问题。

这是一个非常相似的例子:

https://stackoverflow.com/a/28431346/46588

使代码工作的最安全方法是确保它可以作为表达式运行,并检查SyntaxError源链接以查看实际执行代码是什么,并从中反向设计解决方案。通常它意味着一对策略性地放置括号。

简而言之:控制台尝试尽可能准确地模拟全局执行上下文,但由于与v8引擎和JavaScript语义交互的限制,这有时很难或无法解决。

答案 3 :(得分:0)

我问了这样一个问题:

@getify我有一个问题:要产生#IIFE模式,我们在函数声明周围使用paran将其转换为函数表达式,然后调用它。现在在箭头功能IIFE中,为什么我们需要帕兰斯?默认情况下,箭头功能是否已经是表达式?!

这是凯尔·辛普森的答案:

箭头函数是一个expr,但是我们需要将“操作符优先级”(sorta)周围的括号b / c括起来,以便将最终的括号调用arrow-IIFE应用于整个函数而不仅仅是它身体的最后一个标记。

x => console.log(x)(4)

vs

(x => console.log(x))(4)

-getify(@getify)June 12, 2020