javascript 函数领先!句法

IT技术 javascript syntax
2021-01-28 04:33:41

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

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

作为更常见的替代品

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

用于自调用匿名函数。

我想知道一些事情。首先,是什么让顶级示例真正起作用?为什么需要 bang 才能使这个语句在语法上正确?我也被告知这+有效,我相信其他一些代替!

第二,有什么好处?我只能说它节省了一个角色,但我无法想象这是一个吸引众多采用者的巨大好处。我还缺少其他什么好处吗?

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

6个回答

理想情况下,您应该能够简单地完成所有这些:

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

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

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

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

或者为了好玩:

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

或者:

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

甚至:

~function(){
  // do stuff
  return 0;
}( );
我已将上述所有选项添加到性能测试中:jsperf.com/bang-function
2021-03-16 04:33:41
如果缺少分号,您的两个一元运算符可以解释为二元运算符。第一个和最后一个是这些示例中最安全的。
2021-03-16 04:33:41
我会说表达能力。在这种情况下,速度并不重要,因为它运行一次。
2021-03-21 04:33:41
那么唯一的好处是简洁?
2021-03-29 04:33:41
出于好奇,我注意到 no bang 和 bang 的执行速度最快,但至少在 Chrome 的进化过程中,bang 比 no bang 更快。(可能在统计上无关紧要,但是...)有什么原因吗?我对引擎盖下的代码知之甚少,但发现它非常吸引人。
2021-04-04 04:33:41

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

function doSomething() {
}

一个自调用函数,如

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

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

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

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

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

这个“以函数开头的行是预期的......”看起来很模糊。那这个呢:var foo = {CR/LF here} function bar() {}
2021-04-08 04:33:41

除了已经说过的事情之外,使用 ! 如果您编写没有分号的 javascript,则很有用:

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

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

第一个示例按预期输出 'ham',但第二个示例将抛出错误,因为 i = 2 语句由于以下括号而未终止。

同样在连接的 javascript 文件中,您不必担心前面的代码是否缺少分号。所以不需要常见的 ;(function(){})(); 以确保您自己的不会破裂。

我知道我的回答有点晚了,但我认为还没有提到它:)

是的,你是对的。如果将它们放在同一行上,则会出现错误。我没有想过。但是,到目前为止我使用的任何连接脚本/库都没有做到这一点。当您缩小和连接您的文件时,会添加分号。所以,老实说,我无法想象你会遇到那个问题的情况。另一方面,现在是凌晨 2 点,我可能是无知的:)
2021-03-16 04:33:41
这实际上不是真的。考虑以下示例: !function(){console.log("ham");}()!function(){console.log("cheese")}(); 你会收到一个错误:“语法错误:意外的令牌!”
2021-03-28 04:33:41
+1 为小费和回忆...现在没有人喜欢编写没有分号的 javascript。
2021-03-30 04:33:41
Twitter Bootstrap 全是没有分号的 JS,而且它很新……(对不起,如果上面的评论本质上是讽刺而我错过了它)。
2021-04-03 04:33:41

一方面,jsPerf 表明使用!(UnaryExpression's) 通常更快。有时它们是平等的,但当它们不是时,我还没有看到非撞击的一个战胜其他人太多:http : //jsperf.com/bang-function

这是在最新的 Ubuntu 上使用最旧的(据说..)Chrome 版本 8 进行测试的。所以结果当然可能会有所不同。

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

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

或者void

void function() {
   alert("Hi!"); 
}();
@brad 一定与 safari 有关,如果您查看测试,大多数其他浏览器似乎都偏爱!. 但我也想找到一个关于这个的理论:)
2021-03-26 04:33:41
有趣的!虽然在 Safari 速度方面我得到了大约 50/50,但非碰撞肯定有自己的。我想知道潜在的速度差异是否有一些理论?
2021-03-27 04:33:41
我喜欢 void 因为它明确表示“我不在乎返回值”,并且因为它让我想起了其他语言中的约定
2021-04-05 04:33:41

所以,用否定“!” 以及所有其他一元运算符,如 +、-、~、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!"); 
}();

将三元留给其他人:)

0?0:function() { alert("Hi!"); }();
2021-03-25 04:33:41
宾果游戏,丹!我们有三元的 ;)
2021-03-26 04:33:41