JavaScript匿名函数调用语法

4
这两者之间有何区别:
(function () {
    alert('something');
})();​  # invocation parens after the wrapping parens

并且

(function () {
    alert('something');
}());  # invocation parens inside the wrapping parens

它们都会给我相同的结果:弹出 "something" 的提示。


没有功能上的区别。括号是为了将函数转换为表达式,但它们关闭的位置并不重要。 - Bergi
3个回答

10

没有区别。两者都会执行相同的操作(调用匿名函数表达式)。

括号仅仅是为了确保该函数被解析为一个表达式,而不是声明(这很重要,因为声明不能被调用)。你还可以看到其他运算符起到相同的作用,例如:

// All three of the following have the same effect:

!function () {
    alert('something');
}();​

+function () {
    alert('something');
}();​

(function () {
    alert('something');
}());​

请注意,如果您使用像JSLint这样的静态分析工具,它可能会抱怨您在问题中使用的第一种形式(调用括号在分组运算符外部)。这是因为有些人认为第二种形式更容易理解。


我从来不知道你也可以使用 !+ 来做那件事。好信息。 - Cerbrus
你可以使用几乎任何运算符,这就是为什么 something = function () {} (); 也能够工作的原因。 - Misha Reyzlin
1
@Cerbus,也可以使用位运算符:~function(){}(); 有时会被使用。任何使函数声明成为语句的一部分(从而使函数声明成为表达式的一部分)的东西都可以工作:var ignoreMe = function(){}(); 同样适用。但这就是这个非常清楚地解释的内容:+1。 - Elias Van Ootegem
@ShlomiSasson - ! 是“逻辑非”运算符,它将否定函数的返回值。在这个上下文中,+ 是一元加号运算符,它将函数的返回值转换为数字。 - James Allardice
@JamesAllardice,你的意思是上面的例子只是使用运算符作为“技巧”使示例工作吗?(因为仅使用 function () {alert('something');}(); 就会抛出错误) - Shlomi
但是 + 和 () 在自动分号插入(ASI)的情况下与 ! 不同,因为前者在不结束语句/表达式的情况下会有不同的行为。如果前面的代码没有结束语句/表达式,则 () 和 + 都会触发两个表达式合并,+ 将它们相加,() 用第二个表达式作为参数调用第一个表达式。这就是为什么一些代码使用 ! 运算符,特别是在编写无分号代码时,以确保无论前面的代码如何,都不会受到函数调用的影响。 - mknecht

3
JSLint把})();的调用视为"错误"。函数定义和调用是单个表达式的一部分。正因为这个原因,调用本身就是表达式的一部分,这是很合理的。
实际上,这只是个人偏好的问题。个人而言,我认为
(function(elem)
{
})(document.getElementById('foo'));

比较易读
(function(elem)
{
}(document.getElementById('foo')));

然而,任何具备语法高亮功能的编辑器都可以消除这个论点。
最重要的是:使用你感觉最舒适的方式,并让 JSLint 来批评它。Douglas Crockford 是JS领域的权威人物,但这并不意味着我们所有人都必须盲目地复制他的风格/理念。


0

将某物用括号括起来(在JS中)会强制解释器将其视为表达式。

在第一种情况下,您强制解释器将函数视为表达式,然后解释器评估它,得出它是一个函数,然后继续查找:(),因此它调用该函数。

在第二种情况下,您还要求解释器将调用的 parens 视为表达式,因此如果函数调用返回值(否则它将未定义 - 感谢Elias van Ootegem),则函数调用的结果将是表达式的结果。


谢谢!因此,两者之间有区别(不像上面有些人说的那样),只是在返回值方面而已,我认为这很重要要知道.. :) TA。 - Shlomi
1
@ShlomiSasson - 分组运算符 返回的结果有所不同。它将返回一个匿名函数(然后立即调用该函数)或该函数的返回值(因为在计算组时已经立即调用)。因此,这两者之间没有功能上的区别(您可以通过将表达式的结果分配给变量,然后检查其值来尝试此操作)。 - James Allardice
在JS中,函数调用的结果从不是void类型。如果没有显式的return语句,函数将返回undefined。此外,看起来好像你确实说这两种符号的计算方式有所不同,并且这种区别反映在表达式解析的值中,但事实并非如此:(function(){}())<--为了让JS知道要调用什么,函数声明必须单独进行评估。 - Elias Van Ootegem
谢谢指出返回undefined,我是这个意思但忘了这个词...但我的意思是这种区别反映在括号内表达式的结果中。@EliasVanOotegem - 11684
@11684:哦,现在我明白你的意思了,当然你关于“分组表达式”的结果值是正确的,我以为你指的是整个语句的结果值会有所不同。 - Elias Van Ootegem
1
不,我不是那个意思,虽然我必须承认我没有表达清楚。@EliasVanOotegem - 11684

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接