【问题标题】:Location of parenthesis for auto-executing anonymous JavaScript functions?自动执行匿名 JavaScript 函数的括号位置?
【发布时间】:2011-03-24 00:09:38
【问题描述】:

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

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

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

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

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

CMS 在Explain JavaScript’s encapsulated anonymous function syntax 接受的答案中有一条评论说“(function(){})();(function(){}()); 都是有效的。”

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

【问题讨论】:

标签: javascript syntax anonymous-function iife


【解决方案1】:

它们几乎相同。

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

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

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

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

【讨论】:

  • JSLint 想要“(function(){}());”。 JSLint 说:“将调用移动到包含函数的括号中。”
  • 其实你并不局限于这两个,你可以使用任何使编译器意识到函数是表达式的一部分而不是语句的东西,例如+function(){}()!function(){}()
  • @XP1:JSLint 想要很多 Crockford style 特有的东西,而不是实质性的东西。这是其中之一。
  • @T.J.Crowder。你会推荐什么? jQuery 使用第一种风格,Crockford 使用第二种风格。
  • @ThorpeObazee:真的没关系,所以随心所欲。我建议不要使用一些更奇怪的操作符(-function(){}();!function(){}();,基本上function 之前的任何其他运算符也可以使用,但我会坚持使用括号的版本)。我看到第一个比第二个多很多,这是我的偏好;这对我来说也更有意义,但这是主观的。 FWIW:jsbin.com/ejaqow
【解决方案2】:

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

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

(foo || bar)()

【讨论】:

  • 为了向其他读者澄清(主要是因为我自己一开始并不理解它:)), foo 和/或 bar 必须已经等于某些功能。 (例如foo = function(){alert('hi');}。如果两者都不是函数,则会引发错误。
  • @AlexanderBird 进一步澄清 - 如果foo 是“真实的”但不是函数,它也会抛出错误。
【解决方案3】:

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

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

考虑:

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

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

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

外部括号是不必要的:

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

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

所以它归结为:

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

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

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

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

【讨论】:

  • 请注意,arguments.callee 自 ES5 以来已被弃用(并且在严格模式下被禁止)。
  • “外部括号是不必要的:” - 我认为它们可以防止文件连接时出错,否则你需要一个 !什么的。
【解决方案4】:

之所以存在差异,是因为 Douglas Crockford 不喜欢IIFEs 的第一个样式! (严重)As you can see in this video!!.

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

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

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

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

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

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

【讨论】:

    猜你喜欢
    • 2011-10-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多