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

IT技术 javascript syntax anonymous-function iife
2021-01-26 02:22:12

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

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

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

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

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

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

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

4个回答

它们几乎相同。

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

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

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

> function(){}()
SyntaxError: Unexpected token (
> (function(){})()
undefined
> (function(){return 'foo'})()
"foo"
> (function(){ return 'foo'}())
"foo"
JSLint 想要“(function(){}());”。JSLint 说,“将调用移动到包含函数的括号中。”
2021-03-11 02:22:12
@ThorpeObazee:这真的无关紧要,所以随心所欲。我建议不要使用一些更奇怪的操作符-function(){}();, !function(){}();,基本上任何其他操作符function也可以工作,但我会坚持使用括号的版本)。我看到的第一个很多比我更看到第二个,这是我的偏好; 这对我来说也更有意义,但这是主观的。FWIW:jsbin.com/ejaqow
2021-03-28 02:22:12
实际上,您不仅限于这两个,您几乎可以使用任何使编译器意识到该函数是表达式的一部分而不是语句的东西,例如+function(){}()or !function(){}()
2021-03-30 02:22:12
@XP1:JSLint 想要很多特定于 Crockford风格的东西,而不是实质性的东西。这是其中之一。
2021-03-30 02:22:12
@TJCrowder。你会推荐什么?jQuery 使用第一种样式,Crockford 使用第二种样式。
2021-04-09 02:22:12

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

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

(foo || bar)()
为了向其他读者澄清(主要是因为我自己一开始并不理解:)), foo 和/或 bar 必须已经等于某个函数。(例如foo = function(){alert('hi');}。如果两者都不是函数,则会引发错误。
2021-03-17 02:22:12
@AlexanderBird 进一步澄清 - 如果foo“真实”但不是函数,它也会抛出错误
2021-04-03 02:22:12

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

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

考虑:

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

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

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

外部括号是不必要的:

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

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

所以它归结为:

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

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

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

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

请注意,arguments.callee自 ES5 起已弃用(并在严格模式下被禁止)。
2021-03-16 02:22:12
“外部括号是不必要的:” - 我认为它们可以防止文件连接时出现错误,否则你需要一个 ! 或者其他的东西。
2021-03-17 02:22:12

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

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

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

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

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

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

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