javascript函数领先!语法

javascript函数领先!语法,javascript,syntax,Javascript,Syntax,我已经在一些库中看到了这种语法,我想知道它的好处是什么。(注意,我很清楚闭包和代码在做什么,我只关心语法上的差异) 作为更常见的 (function(){ // do stuff })(); 用于自调用匿名函数 我想知道一些事情。首先,是什么让顶级示例真正起作用?为什么为了使这句话在语法上正确,必须使用bang?还有人告诉我,+是有效的,我相信还有一些人可以代替 第二,好处是什么?我所能说的是,它只保存了一个角色,但我无法想象这能带来如此巨大的好处来吸引众多的用户。我还缺少其他好处吗 我能

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

作为更常见的

(function(){
  // do stuff
})();
用于自调用匿名函数

我想知道一些事情。首先,是什么让顶级示例真正起作用?为什么为了使这句话在语法上正确,必须使用bang?还有人告诉我,
+
是有效的,我相信还有一些人可以代替

第二,好处是什么?我所能说的是,它只保存了一个角色,但我无法想象这能带来如此巨大的好处来吸引众多的用户。我还缺少其他好处吗


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

首先,jsPerf表明使用
(UnaryExpression的)通常更快。有时他们表现出平等,但当他们不平等时,我还没有看到非砰砰声的一个战胜了其他人:

这是在最新的Ubuntu上用最旧的Chrome 8版进行测试的。所以结果当然可能不同

编辑:像
删除这样疯狂的东西怎么样

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

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

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

function(){
  // do stuff
}(); 
这意味着声明匿名函数并执行它。但由于JS语法的特殊性,这将不起作用

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

或者为了好玩:

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

甚至:

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

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

function doSomething() {
}
像这样的自调用函数

function(){
  // do stuff
}();
不适合该形式(并且在第一个打开参数时会导致语法错误,因为没有函数名),因此括号用于描述匿名函数表达式

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


我不知道这个约定,但如果它变得普遍,它可能有助于可读性。我的意思是,任何人阅读一大块代码顶部的
!函数
,都会期望进行自调用,就像我们看到
(函数
。除了我们会丢失那些恼人的括号之外。我想这就是原因,而不是节省速度或字符数。

除了前面已经说过的内容,如果编写javascript时不使用分号,则带有!的语法非常有用:

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

i = 2
(function(){
  console.log('cheese')
})()
第一个示例按预期输出'ham',但第二个示例将抛出错误,因为i=2语句由于以下括号未终止

同样,在连接的javascript文件中,您不必担心前面的代码是否缺少分号。因此,不需要使用公共;(function(){}();来确保您自己的代码不会中断

我知道我的答案有点晚了,但我想我还没有提到:)

所以,对于否定“!”和所有其他一元运算符,如+、-、~、delete、void,已经讲了很多了,总结一下:

!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

框架确实喜欢保存尽可能多的迷你们无法优化的字符;两个例子都实现了这一点。如前所述,我理解这些函数在做什么,我更感兴趣的是句法上的差异。我将其归因于可爱的需要,嗯,比以前的团队更复杂的要求。“哦,那些附加异教,我们有!!“我从来都不知道这件事,太棒了。我喜欢
,因为它强调了它的执行。有趣!我得到了大约50/50,虽然在Safari速度方面,非碰撞当然有它自己的。我想知道是否有一些关于潜在速度差异的理论?@brad一定与Safari有关,如果你看一下测试,大多数其他的浏览器似乎更喜欢
。但我也想找到一个关于这一点的理论:)我喜欢void,因为它明确表示“我不在乎返回值”“,因为它让我想起了其他语言中的约定,那么简洁性的唯一好处是什么呢?我已经在性能测试中添加了上述所有选项:我想说的是表达能力。在这种情况下,速度并不重要,因为它只运行过一次。出于好奇,我注意到“砰”和“砰”的表现最快,但至少在Chrome的进化过程中,砰变得比“砰”更快。(可能在统计上无关紧要,但…)有什么原因吗?我对幕后的代码了解不多,但我觉得它非常有趣。如果缺少分号,两个一元运算符可以解释为二进制。第一个和最后一个是这些例子中最安全的。提示和记忆+1…现在没有人喜欢写没有分号的javascript。Twitter引导是没有分号的JS,非常新。。。(很抱歉,如果上面的评论是讽刺性质的,我错过了)。事实并非如此。考虑下面的例子:函数(){console.log(“ham”);}()!功能
!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!"); 
}();
(function(){}()); -> 76,827,475 ops/sec

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

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