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

自动执行匿名JavaScript函数的括号位置?,javascript,syntax,anonymous-function,iife,Javascript,Syntax,Anonymous Function,Iife,最近,我将的当前版本与项目中的版本进行了比较,发现函数表达式的创建和自执行方式有所不同 用于将匿名函数包装在括号中然后执行它的代码 (function () { // code here })(); 但现在它将自动执行的函数封装在括号中 (function () { // code here }()); CMS在接受的答案中有一条评论:“这两个:(function(){}();和(function(){}());都是有效的。” 我想知道有什么区别?前者是否通过留下一个全局匿名函数来占

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

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

(function () {
  // code here
})();
但现在它将自动执行的函数封装在括号中

(function () {
  // code here
}());
CMS在接受的答案中有一条评论:“这两个:
(function(){}();
(function(){}());
都是有效的。”


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

它们实际上是一样的

> function(){}()
SyntaxError: Unexpected token (
> (function(){})()
undefined
> (function(){return 'foo'})()
"foo"
> (function(){ return 'foo'}())
"foo"
第一个函数用括号括起函数,使其成为有效表达式并调用它。表达式的结果未定义

第二个执行函数,自动调用周围的括号使其成为有效表达式。它的计算结果也是未定义的

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

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

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

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

(foo || bar)()

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

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

考虑:

(函数名为dfunc(){…}())

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

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

外部参数是不必要的:

(namedfunc = function namedfunc () { ... })()
但无论如何,你都不想要那个全球宣言,是吗

因此,它可以归结为:

(function namedfunc () { ... })()
您还可以进一步减少它:名称是不必要的,因为它永远不会被使用(除非您的函数是递归的..即使这样,您也可以使用
参数。被调用方


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

差异只是存在,因为道格拉斯·克罗克福德不喜欢这首歌的第一款!(严重地)

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

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

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

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

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

所有这些都和你的选择完全一样。在这些案例中进行选择完全靠你自己&没有什么区别。{带有
()
的文件会产生1字节大的文件;-)}

JSLint想要的“(function(){}());”。JSLint说,“将调用移到包含函数的参数中。”实际上,您不限于这两个参数,您可以使用任何使编译器意识到函数是表达式而不是语句的一部分的东西,例如
+function(){}()
!function(){}()
@XP1:JSLint需要很多特定于Crockford风格的东西,而不是实质性的东西。这是其中之一。@T.J.Crowder。你推荐什么?jQuery使用第一种样式,Crockford使用第二种样式。@ThorpeObazee:这真的不重要,所以你可以随心所欲。我建议不要使用一些更高级的操作符(
-function(){}();
!function(){}();
,基本上是在
函数
也起作用之前的任何其他操作符,但我坚持使用paren的版本)。我看到第一个比看到第二个多得多,这是我的偏好;这对我来说也更有意义,但这是主观的。FWIW:为了向其他读者澄清(主要是因为我一开始不理解它:),foo和/或bar必须已经具有相同的功能。(例如,
foo=function(){alert('hi');}
。如果两者都不是函数,则会抛出一个错误。@AlexanderBird进一步澄清-如果
foo
是“truthy”而不是函数,则也会抛出一个错误。另请参阅和相关:(在JSLint中)阅读有关,或检查a()(也)。有关为什么需要括号,请参阅。请注意,自ES5以来,
参数.callee
已被弃用(并且在严格模式下被禁止)。“外部参数是不必要的:“-我认为它们可以防止在连接文件时出错,否则您将需要一个!或其他东西。”。