111

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

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

(function () {
  // code here
})();

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

(function () {
  // code here
}());

CMS 在解释 JavaScript 的封装匿名函数语法的接受答案中有一条评论,即“两者:(function(){})();并且(function(){}());都是有效的”。</p>

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

4

4 回答 4

66

它们几乎相同。

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

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

我认为没有“正确”的做法,因为表达式的结果是相同的。

> function(){}()
SyntaxError: Unexpected token (
> (function(){})()
undefined
> (function(){return 'foo'})()
"foo"
> (function(){ return 'foo'}())
"foo"
于 2010-08-02T01:49:17.893 回答
13

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

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

(foo || bar)()
于 2010-08-02T01:49:36.893 回答
10

除了语法之外没有任何区别。

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

考虑:

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

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

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

外部括号是不必要的:

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

但无论如何你都不想要那个全局声明,是吗?

所以它归结为:

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

你可以进一步减少它:这个名字是不必要的,因为它永远不会被使用(除非你的函数是递归的......即使那样你也可以使用arguments.callee

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

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

于 2010-08-02T02:35:58.937 回答
-2

之所以存在差异,是因为 Douglas Crockford不喜欢IIFE的第一种风格!(严肃地)正如你在这个视频中看到的那样!!.

存在额外包装 {in both styles} 的唯一原因()是帮助制作该部分代码Function Expression,因为无法立即调用函数声明。一些脚本/缩小器只使用+, !, -&~而不是括号。像这样:

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

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

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

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

所有这些都与您的替代方案完全相同。在这些案例中进行选择完全取决于您自己,没有任何区别。{()产生1 字节大文件的那些;-) }

于 2017-02-24T15:25:02.983 回答