函数在分配给变量时有效,但在自身执行时抛出SyntaxError

时间:2018-05-23 12:45:25

标签: javascript

我有一个像这样的IIFE:

(function a() {
    return "b";
}());

在控制台中执行,它返回"b"

我删除了第一组括号,认为这会使“a”函数成为全局函数,但仍然有效,并返回"b"

function a() {
   return "b";
}();

但它抛出SyntaxError

Uncaught SyntaxError: Unexpected token )

然后,我尝试通过分配变量将函数转换为表达式,并且它起作用了:

var c = function a() {
   return "b";
}();
console.log(c); // prints b

为什么会这样?为什么它作为表达而不是单独工作?

1 个答案:

答案 0 :(得分:4)

第二段代码不是它的样子。

此代码看起来像是一个立即执行的函数:

function a() {
    return "b";
}()

但实际上,它只是一个函数声明,后跟一个空表达式,这是不允许的:

function a() {
    return "b";
}

() // not allowed - empty expression

Ben Alman在article关于IIFE的论文中解释了这一点:

  

当解析器在全局范围内遇到function关键字时   在函数内部,它将其视为函数声明(语句),   而不是作为函数表达式,默认情况下。

     

...

     

虽然在表达后放置的parens表示表达式   是一个要调用的函数,在语句之后放置的parens   与前面的陈述完全分开,只是一个   分组运算符(用作控制优先级的方法)   评价)。

分组运算符需要包含要评估的表达式。它本身没有任何意义:

() // meaningless
2 + 3 * 4 // 15
(2 + 3) * 4 // 20

在IIFE中,外括号只是强制解析器期望表达式的一种方法。

这就是表达式var c = function() { return "b"; }();也有效的原因;这是因为解析器因为赋值给c而知道期望表达式。

旁注

Alman还建议在分配变量时使用自调用函数而不使用外括号(即var v = function(){...}()),因为这是不好的做法:

  

如果额外的“消歧”围绕着   函数表达式是不必要的(因为解析器已经   期待一个表达式,在制作时使用它们仍然是个好主意   一项任务,作为惯例。

     

这样的parens通常表示函数表达式将是   立即调用,变量将包含的结果   功能,而不是功能本身。这可以节省读书的人   编码必须向下滚动到可能的底部的麻烦   是一个非常长的函数表达式,以查看它是否已被调用或   不