Javascript函数前导bang !语法

我现在已经在一些库上看到了这种语法,我想知道它的好处是什么。(注意我很清楚闭包和代码在做什么,我只关心语法差异)

!function(){
// do stuff
}();

作为更常见的替代品

(function(){
// do stuff
})();

用于自调用匿名函数。

我在想一些事情。首先,是什么让上面的例子真正起作用?为什么为了使这个陈述在语法上正确,bang是必要的?我还被告知+可以工作,我相信还有其他一些工作,可以代替!

第二,好处是什么?我所知道的是,它节省了一个角色,但我无法想象这有如此大的好处来吸引大量的采用者。我还错过了什么好处吗?

我能看到的唯一的其他区别是自调用函数的返回值,但在这两个例子中,我们并不真正关心函数的返回值,因为它只用于创建一个闭包。有人能告诉我为什么要用第一种语法吗?

20721 次浏览

首先,jsPerf表明使用! (UnaryExpression的)通常更快。有时它们是平等的,但当它们不是,我还没有看到non-banged一个比其他的胜利太多:http://jsperf.com/bang-function

这是在最新的Ubuntu上测试的,使用的是最老的Ubuntu(每个说..)Chrome,版本8。所以结果当然可能不同。

编辑:像delete这样疯狂的东西怎么样?

delete function() {
alert("Hi!");
}();

还是void ?

void function() {
alert("Hi!");
}();

理想情况下,你应该能够简单地做到这一切:

function(){
// do stuff
}();

这意味着声明匿名函数并执行它。但由于JS语法的特殊性,这将不起作用。

因此,实现这一点的最短形式是使用一些表达式,例如UnaryExpression(以及CallExpression):

!function(){
// do stuff
}();

或者为了好玩:

-function(){
// do stuff
}();

或者:

+function(){
// do stuff
}();

甚至:

~function(){
// do stuff
return 0;
}( );

在Javascript中,以function开头的行被认为是一个函数声明,并且应该是这样的

function doSomething() {
}

像这样的自调用函数

function(){
// do stuff
}();

不符合该形式(并且会在第一个开括号处导致语法错误,因为没有函数名),因此括号用于描述匿名函数表达式

(function(){
// do stuff
})();

但是任何创建表达式(而不是函数语句)的东西都可以,因此有了!。它告诉解释器这不是一个函数语句。除此之外,运算符优先级指示函数在求反之前调用。

我不知道这个惯例,但如果它变得普遍,它可能有助于可读性。我的意思是,任何在大块代码顶部阅读!function的人都将期望自我调用,就像我们在看到(function时已经习惯于期望同样的方式一样。除了这些烦人的圆括号。我认为这就是原因,而不是速度或角色数量上的节省。

除了已经说过的内容,还有!如果你编写的javascript没有分号,这个函数是有用的:

var i = 1
!function(){
console.log('ham')
}()


i = 2
(function(){
console.log('cheese')
})()

第一个示例如预期的那样输出'ham',但第二个示例将抛出一个错误,因为i = 2语句没有因为下面的括号而终止。

此外,在连接的javascript文件中,您不必担心前面的代码是否缺少分号。因此不需要common;(function(){})();确保你自己的不会坏。

我知道我的回答有点晚了,但我想它还没有被提及:)

因此,使用否定“!”和所有其他一元运算符,如+,-,~,delete, void,已经告诉了很多,只是总结一下:

!function(){
alert("Hi!");
}();

void function(){
alert("Hi!");
}();

delete function(){
alert("Hi!");
}();

为了好玩,还有一些二元操作符的情况:)

1 > function() {
alert("Hi!");
}();

1 * function() {
alert("Hi!");
}();

1 >>> function() {
alert("Hi!");
}();

甚至

1 == function() {
alert("Hi!");
}();

把三元留给其他人,伙计们:)

正如你所看到的在这里,在javascript中实现自调用方法的最好方法是使用:

(function(){}()); -> 76,827,475 ops/sec


!function(){}();  -> 69,699,155 ops/sec


(function(){})(); -> 69,564,370 ops/sec