关于语法:自动执行匿名JavaScript函数的括号的位置?

Location of parenthesis for auto-executing anonymous JavaScript functions?


我最近将当前版本的json2.js与我在项目中的版本进行了比较,并注意到函数表达式的创建和自我执行方式有所不同。


用于在括号中包装匿名函数然后执行它的代码,

1
2
3
(function () {
  // code here
})();


但现在它将自动执行的函数包含在括号中。

1
2
3
(function () {
  // code here
}());


CMS在解释JavaScript的封装匿名函数语法的接受答案中有一条评论"两者:(function(){})();(function(){}());都有效"。


我想知道有什么区别? 前者是否通过绕过全局匿名函数来占用内存? 括号应该放在哪里?



他们几乎是一样的。


第一个包围函数的括号,使其成为有效的表达式并调用它。表达式的结果是未定义的。


第二个执行函数,自动调用周围的括号使其成为有效的表达式。它还评估为undefined。


我不认为有一种"正确"的方式,因为表达的结果是相同的。

1
2
3
4
5
6
7
8
> function(){}()
SyntaxError: Unexpected token (
> (function(){})()
undefined
> (function(){return 'foo'})()
"foo"
> (function(){ return 'foo'}())
"foo"



在那种情况下无所谓。您正在调用一个表达式,该表达式解析为第一个定义中的函数,并在第二个示例中定义并立即调用函数。它们是相似的,因为第一个例子中的函数表达式只是函数定义。


还有其他更明显有用的案例用于调用解析为函数的表达式:

1
(foo || bar)()



语法之外没有任何区别。


关于您对第二种方法的担忧:


考虑:


(function namedfunc () { ... }())


即使您提供了名称,namedfunc仍将不在全局范围内。匿名函数也是如此。获得该范围的唯一方法是将其分配给parens内的变量。

1
((namedfunc = function namedfunc () { ... })())


外围是不必要的:

1
(namedfunc = function namedfunc () { ... })()


但你还是不想要全球宣言,是吗?


所以它归结为:

1
(function namedfunc () { ... })()


并且你可以进一步减少它:名称是不必要的,因为它永远不会被使用(除非你的函数是递归的......甚至你可以使用arguments.callee)

1
(function () { ... })()


这就是我想到的方式(可能不正确,我还没有读过ECMAScript规范)。希望能帮助到你。



差异只是因为道格拉斯·克罗克福德不喜欢IIFE的第一种风格! (seriuosly)正如你在这个视频中看到的!!


存在额外包装() {在两种样式中}的唯一原因是帮助使代码段功能表达式,因为无法立即调用函数声明。一些脚本/缩小器只使用+!-& ~而不是括号。像这样:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
+function() {  
    var foo = 'bar';  
}();

!function() {  
    var foo = 'bar';  
}();

-function() {  
    var foo = 'bar';  
}();

~function() {  
    var foo = 'bar';  
}();


所有这些都与您的选择完全相同。在这些案例中进行选择完全取决于你自己和他们。没有区别。 {()生成1字节更大的文件;-)}