自动执行匿名JavaScript函数的括号位置?


107

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

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

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

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

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

有通过CMS在接受答案的注释解释JavaScript的封装匿名函数的语法是“既:(function(){})();(function(){}());有效。”

我想知道有什么区别吗?前者是否通过留下全局匿名函数来占用内存?括号应位于何处?



相关:立即函数调用语法(在JSLint中)
Bergi 2014年

1
还请阅读有关此构造目的的信息,或检查(技术解释(也在此处)。关于为什么需要括号,请参阅此问题
Bergi 2014年

Answers:


66

它们实际上是相同的。

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

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

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

> function(){}()
SyntaxError: Unexpected token (
> (function(){})()
undefined
> (function(){return 'foo'})()
"foo"
> (function(){ return 'foo'}())
"foo"

8
JSLint需要“((function(){}());;)””。JSLint说:“将调用移到包含该函数的括号中。”
XP1

27
实际上,您不仅限于这两种,还可以使用使编译器意识到该函数是表达式而不是语句的一部分的任何东西,例如+function(){}()!function(){}()
Tgr

49
@ XP1:JSLint想要很多特定于Crockford 风格的东西,而不是实质性的东西。这就是其中之一。
TJ Crowder

@TJCrowder。你会推荐什么?jQuery使用第一种样式,而Crockford使用第二种样式。
Teej 2012年

4
@ThorpeObazee:真的没关系,所以随便你怎么做。我建议不要使用一些比较荒谬的方法(-function(){}();!function(){}();和,基本上function也可以使用其他运算符,但是我会坚持使用parens的版本)。我看到的第一个很多比我更看到第二个,这是我的偏好; 这对我来说也更有意义,但这是主观的。FWIW:jsbin.com/ejaqow
TJ Crowder

13

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

对于调用解析为函数的表达式,还有其他更有用的情况:

(foo || bar)()

3
为了向其他读者澄清(主要是因为我自己一开始并不了解:)),foo和/或bar必须已经等于某些功能。(例如foo = function(){alert('hi');},如果既不是一个函数,则会引发错误。
亚历山大鸟

3
@AlexanderBird进一步说明-如果它foo是“真”但不是函数,则也会抛出错误。
JLRishe 2014年

9

除了语法没有什么区别。

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

考虑:

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

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

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

外部括号是不必要的:

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

但是您仍然不希望该全局声明,对吗?

因此可以归结为:

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

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

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

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


请注意,arguments.callee自ES5起已弃用(在严格模式下禁止使用)。
nyuszika7h 18/12/26

“外部括号是不必要的:”-我认为当文件串联时,它们可以防止错误,否则您需要!或者其他的东西。
Jimmyt1988 '19

-3

之所以存在差异,是因为Douglas Crockford 不喜欢IIFE的第一种样式!(严重)正如您在此视频中看到的那样!

(){这两种样式}中都存在额外包装的唯一原因是为了帮助使该部分代码成为函数表达式,因为不能立即调用函数声明。一些脚本/缩小-ERS刚刚使用+!-~,而不是太括号。像这样:

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

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

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

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

所有这些与您的替代品完全相同。这些情况之间的选择完全由您自己决定,没有任何区别。{ ()产生1个字节大文件的文件 ;-)}

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.