Javascript ES6立即调用了arrow函数

Javascript ES6立即调用了arrow函数,javascript,node.js,arrow-functions,Javascript,Node.js,Arrow Functions,为什么这在Node.js控制台(在4.1.1和5.3.0中测试)中有效,但在浏览器(在Chrome中测试)中无效 此代码块应创建并调用记录Ok的匿名函数 () => { console.log('Ok'); }() 此外,尽管上述在Node.js中起作用,但这不起作用: n => { console.log('Ok'); }() 这也不是: (n) => { console.log('Ok'); }() 奇怪的是,当添加参数时,它实际上会在立即调用的部分抛出一

为什么这在Node.js控制台(在4.1.1和5.3.0中测试)中有效,但在浏览器(在Chrome中测试)中无效

此代码块应创建并调用记录
Ok
的匿名函数

() => {
  console.log('Ok');
}()
此外,尽管上述在Node.js中起作用,但这不起作用:

n => {
  console.log('Ok');
}()
这也不是:

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

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

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

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

这在Node.js中起作用而在Chrome中不起作用的可能原因是其解析器将其解释为一个自执行函数,如下所示

function() { console.log('hello'); }();
Node.js中运行良好。这是一个函数表达式,Chrome和Firefox以及大多数浏览器都是这样解释的。您需要手动调用它

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

对于参数化版本
,这将起作用

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

如果没有括号,这些都不应该起作用

为什么?

因为根据规范:

  • 箭头函数是
  • 必须是MemberExpression、SuperCall或CallExpression
  • 因此,ArrowFunction不能位于CallExpression的LHS上


    这在解释
    =>
    时有效地意味着,它与赋值运算符
    =
    +=
    等在同一级别上工作

    意义

    • x=>{foo}()
      不会变成
      (x=>{foo})(
    • 解释器试图将其解释为
      x=>({foo}())
    • 因此,它仍然是一个语法错误
    • 因此,解释器判断
      一定是错误的,并抛出一个语法错误


    Babel上也有一个bug。

    您之所以会看到这样的问题,是因为控制台本身试图模拟当前目标上下文的全局范围。它还试图捕获您在控制台中编写的语句和表达式的返回值,以便将结果显示出来。例如:

    > 3 + 2
    < 5
    
    在节点或
    标记中,它工作正常,但在控制台中,它提供了
    未捕获的SyntaxError:意外标识符
    。它还以
    VMxxx:1
    的形式提供了指向源的链接,您可以单击该链接来检查已评估的源,该链接显示为:

    ({ let a = 3 })
    
    那么它为什么要这样做呢

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

    控制台确实试图通过对代码进行智能化来修复这些边缘情况,但这超出了这个答案的范围,我想,您可以提交一个bug来查看这是否是他们考虑修复的东西。 下面是一个非常相似的例子:

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


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

    我问了一个类似的问题:

    @getify我有一个问题:为了生成一个#iLife模式,我们在函数声明周围使用Paran将其转换为函数表达式,然后调用它。现在在arrow函数IIFEs中,为什么我们需要Paran?!arrow函数在默认情况下不是已经是表达式了吗

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

    arrow函数是一个表达式,但我们需要“运算符优先级”(sorta)的周围参数b/c,以便调用arrow IIFE的最终参数应用于整个函数,而不仅仅是其主体的最后一个标记

    vs


    -getify(@getify)

    第一个示例在
    Node.js中工作,并且实际记录了值。我的问题是为什么它工作?为什么我添加参数时它不工作?我非常熟悉
    IIFE
    s,知道如何修复我的代码。我只是好奇为什么,例如,添加
    n
    参数时,我的
    IIFE
    不工作,e即使它没有参数也能工作。我没有否决,但问题是为什么参数化版本在节点中不工作,而完全相同的定义没有参数——这并不是问匿名函数的节点/浏览器实现之间的区别,这是一个好消息,但它没有回答问题,如前所述before,-当没有参数的完全相同的定义不起作用时,为什么参数化版本在节点中不起作用?但是什么是
    function(){}()
    在arrow函数中?如果我想让函数对象公开的函数表达式避免这种情况。问得好。两个参数化版本都能与BabelOut一起工作,那么
    (n=>{console.log(“Ok”);})(;
    是否有效?是
    (n=>{console.log(“Ok”);})()
    甚至可以在Chrome开发控制台上运行,因此,3年后,答案是?下面3个答案中的一个肯定应该被接受?!@joedotnot我没有得到一个cle
    { let a = 3 }
    
    ({ let a = 3 })
    
    x => console.log(x)(4)    // trouble
    
    (x => console.log(x))(4)    // working