我有一个像这样的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
为什么会这样?为什么它作为表达而不是单独工作?
答案 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通常表示函数表达式将是 立即调用,变量将包含的结果 功能,而不是功能本身。这可以节省读书的人 编码必须向下滚动到可能的底部的麻烦 是一个非常长的函数表达式,以查看它是否已被调用或 不