javascript函数领先爆炸!

javascript function leading bang ! syntax

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

1
2
3
!function(){
  // do stuff
}();

作为更常见的

1
2
3
(function(){
  // do stuff
})();

用于自调用匿名函数。

我想知道一些事情。首先,什么允许顶级示例实际工作?为使这句话句法正确,为什么需要砰的一声?还有人告诉我,+起作用了,我确信还有其他一些替代了!的作用。

第二,有什么好处?我能说的是,它节省了一个字符,但我不能想象这是一个巨大的好处,以吸引众多的采纳者。我还缺少其他的好处吗?

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


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

1
2
3
function(){
  // do stuff
}();

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

因此,实现这一点的最短形式是使用一些表达式,例如一元表达式(和callexpression):

1
2
3
!function(){
  // do stuff
}();

或者为了好玩:

1
2
3
-function(){
  // do stuff
}();

或:

1
2
3
+function(){
  // do stuff
}();

甚至:

1
2
3
4
~function(){
  // do stuff
  return 0;
}( );


在javascript中,以function开头的行应该是一个函数语句,并且应该看起来像

1
2
function doSomething() {
}

像这样的自调用函数

1
2
3
function(){
  // do stuff
}();

不符合该格式(并且由于没有函数名,将在第一个打开paren时导致语法错误),因此括号用于描述匿名函数表达式。

1
2
3
(function(){
  // do stuff
})();

但是,任何创建表达式(与函数语句相反)的操作都会执行,因此!。它告诉解释器这不是一个函数语句。除此之外,运算符优先级指示在否定之前调用函数。

我不知道这个惯例,但如果它变得普遍,可能有助于可读性。我的意思是,任何在一大块代码顶部阅读!function的人都会期望一个自调用,就像我们在看到(function时所期望的那样。只是我们会失去那些烦人的括号。我希望这就是原因,而不是在速度或字符数上的任何节省。


除了已经说过的内容之外,还有语法和!如果不使用分号编写javascript,则非常有用:

1
2
3
4
5
6
7
8
9
var i = 1
!function(){
  console.log('ham')
}()

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

第一个示例按预期输出"ham",但第二个示例将引发错误,因为I=2语句未因以下括号而终止。

此外,在连接的javascript文件中,如果前面的代码缺少分号,则无需担心。因此,无需使用common;(function())()来确保自己的不会崩溃。

我知道我的回答有点晚了,但我想还没人提到。)


首先,JSperf表明使用EDOCX1(unaryExpression)通常更快。有时它们是相等的,但当它们不相等时,我还没有看到非砰砰的一次胜利比其他的胜利更多:http://jspef.com/bang-function

这是在最新的Ubuntu上测试的,它有最老的(比如说)Chrome版本8。当然,结果可能会有所不同。

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

1
2
3
delete function() {
   alert("Hi!");
}();

或者是void

1
2
3
void function() {
   alert("Hi!");
}();


正如您在这里看到的,在JavaScript中执行自调用方法的最佳方法是使用:

1
2
3
4
5
(function(){}()); -> 76,827,475 ops/sec

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

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


所以,用否定的"!"所有其他一元运算符,如+、-、~、delete、void,都被告知了很多,总而言之:

1
2
3
!function(){
  alert("Hi!");
}();

1
2
3
void function(){
  alert("Hi!");
}();

1
2
3
delete function(){
  alert("Hi!");
}();

还有一些二元运算符的例子。

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

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

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

甚至

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

把三元留给别人。)