我最近将当前版本的json2.js与我项目中的版本进行了比较,并注意到函数表达式的创建和自行执行方式有所不同。
用于在括号中包装匿名函数然后执行它的代码,
(function () {
// code here
})();
但现在它将自动执行的函数包装在括号中。
(function () {
// code here
}());
CMS在Explain JavaScript’s encapsulated anonymous function syntax的接受答案中有一条评论“(function(){})();
和(function(){}());
都有效。”
我想知道区别是什么?前者是否通过绕过全局匿名函数来占用内存?括号应该放在哪里?
答案 0 :(得分:62)
他们几乎是一样的。
第一个包围函数的括号,使其成为有效的表达式并调用它。表达式的结果是未定义的。
第二个执行函数,自动调用周围的括号使其成为有效的表达式。它还评估为undefined。
我认为没有一种“正确”的方式,因为表达的结果是相同的。
> function(){}()
SyntaxError: Unexpected token (
> (function(){})()
undefined
> (function(){return 'foo'})()
"foo"
> (function(){ return 'foo'}())
"foo"
答案 1 :(得分:13)
在这种情况下无所谓。您正在调用一个表达式,该表达式解析为第一个定义中的函数,并在第二个示例中定义并立即调用函数。它们是相似的,因为第一个例子中的函数表达式只是函数定义。
还有其他更明显有用的案例用于调用解析为函数的表达式:
(foo || bar)()
答案 2 :(得分:8)
语法之外没有任何区别。
关于您对第二种方法的担忧:
考虑:
(function namedfunc () { ... }())
namedfunc
仍然不在全球范围内。匿名函数也是如此。获得该范围的唯一方法是将其分配给parens内的变量。
((namedfunc = function namedfunc () { ... })())
外围的parens是不必要的:
(namedfunc = function namedfunc () { ... })()
但你还是不想要那个全球宣言,是吗?
所以归结为:
(function namedfunc () { ... })()
你可以进一步减少它:名称是不必要的,因为它永远不会被使用(除非你的函数是递归的......即使这样你也可以使用arguments.callee
)
(function () { ... })()
这就是我想到的方式(可能不正确,我还没有读过ECMAScript规范)。希望它有所帮助。
答案 3 :(得分:-3)
之所以存在差异,是因为道格拉斯·克罗克福德不喜欢 IIFEs的第一种风格! (seriuosly)As you can see in this video!!。
在两种样式中存在额外包装()
{的唯一原因是帮助制作代码部分功能表达式,因为功能声明不能马上打电话。一些脚本/缩小器只使用+
,!
,-
& ~
而不是括号。像这样:
+function() {
var foo = 'bar';
}();
!function() {
var foo = 'bar';
}();
-function() {
var foo = 'bar';
}();
~function() {
var foo = 'bar';
}();
所有这些都与您的选择完全相同。在这些案例中进行选择完全取决于你自己和他们。没有区别。 ()
生成 1字节更大的文件 ;-)}