function(){}()和!function(){}()有什么区别?

6
可能重复:
!function() { } () vs (function() { })()

我刚阅读Twitter的新版Bootstrap(2.0)源码时注意到自调匿名函数之前有一个感叹号。当我看到这个时,我立刻想:“哦,糟糕,有一种新的更好的方法来做这件事了吗?”。

你可以自己看看!

无论如何,有什么区别?他们的所有JavaScript插件(用于Bootstrap)都一致使用它,所以肯定有原因。

我还注意到另一件事就是在这之后有一个"use strict"。我不认为这与我的先前问题有关,但是有人可以解释一下吗?

谢谢!

3个回答

14
function(){} ();

本身(请参阅Point的评论)不会是有效的,因为

function() {}

是一个函数声明。如果要立即调用它,你需要让JavaScript引擎将该函数视为一个表达式。通常人们会这样做:

(function(){}) ();  //more common

(function(){} ()); // Papa Crockford's preference:

使用

!function(){}();

简单地说,这只是相同事物的简写版本。


+1 虽然后面不是必需的,但根据道格拉斯·克罗克福德的建议,这是一个好习惯 :) - Sarfraz
@gdoron - 我现在已经达到上限了。最好回去工作 :) - Adam Rackis
如果只有第一个,那么它是无效的,但是如果(例如)在它之前有类似于“x =”这样的内容,则可以。 - Pointy
谢谢!我还发现了这篇文章,它是由编写Bootstrap的Javascript的那个家伙撰写的。文章链接:http://www.wordsbyf.at/2011/10/31/i-dont-write-javascript/ - John
@Johnny - 非常棒的文章,我得保存一下。虽然我不认为我是一个足够优秀的开发者,可以像那样省略分号。你必须对语言非常熟悉,才能知道什么时候适用,什么时候会出问题。 - Adam Rackis
值得注意的是,!function(){}() 在 Google 的 Closure 编译器中会抛出“可疑代码”警告,而 ;(function(){})()(function(){}()) 则不会。有趣的是。 - John

8
如果您有两个脚本: :

(function(){

})()

script2.js:

(function(){

})()

当你将它们连接在一起时,你会得到:
(function(){

})()
(function(){

})()

这会导致一个错误,而:
!function(){

}()
!function(){

}()

不。


这也是一些脚本在开头使用分号的原因:;(function(){}()) - hugomg
1
那么,可以说 ;(function(){}())!function(){}() 的作用是相同的吗? - John
分号只是结束一行的符号。如果你不省略它,那么也不会有问题。它的作用与 !function(){}(); 不同。 - bryc

3

ECMAScript语言规范的第12.4节中提到:

ExpressionStatement不能以function关键字开头,因为这会让它与FunctionDeclaration不明确。

如果你想要一个执行匿名函数的表达式语句,你需要绕过此限制。添加一个!(仅仅否定函数的结果)可以使解释器清楚地知道这不是函数声明,避免了歧义。


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