指穷于为薪,火传也,不知其尽也。—《养生主》

Daily English:Experience must be bought.

循环的效率

今天有人问到如何优化一段js代码,我看到他用的是简单的<code>for(;;),我随口说了使用for(in)来优化,因为我觉得for(in)看起来比较短,他觉得不是,他说他以前看过文章,说for(in)的效率低下,于是我作了如下一个测试。

这是for(in)的代码:

Language:  Javascript
var arr=new Array(1000);
var d=new Date();
for (var i=0;i < 100;i++){
  for (a in arr){;}
}
alert(new Date()-d);

这是for(;;)的代码:

Language:  Javascript
var arr=new Array(1000);
var d=new Date();
for (var i=0;i < 100;i++){
  for (var a=0;a < arr .length;a++){;}
}
alert(new Date()-d);

结果令我大吃一惊,for(in)耗时居然为0,而for(;;)却总是无法完成任务…,难道for(in)的效率奇高吗?不可能吧?

我的第一感觉就是for(in)对空数组(数组内容是undefined)感冒,会跳过去,后来作的另一个测试证明了这一点:

Language:  Javascript
var arr=[true,,false,true];
for (a in arr){alert(a)}

这个测试的结果就是数组的第二个元素(为空)会被跳过去。。

在证明了这一点之后,我将程序改为如下:

Language:  Javascript
var arr=new Array(100).join(".;.").split(";");
var d=new Date();
for (var i=0;i < 100;i++){
  for (var a=0;a < arr .length;a++){;}
}
alert(new Date()-d);
d=new Date();
for (var i=0;i < 100;i++){
  for (a in arr){;}
}
alert(new Date()-d);

测试结果证实了网友的说法,for(in)的效率极低,已经不是一个数量级的差距,是10几倍的差距。接下来,我继续深入作了一个测试,把我知道的几种遍历方式都进行了一次比较:

Language:  Javascript
var arr=new Array(1000).join(".;.").split(";");
var d=new Date();
for (var i=0;i < 100;i++){
  for (var a=0;a < arr .length;a++){;}
}
alert("for(;;)="+(new Date()-d));
d=new Date();
for (var i=0;i < 100;i++){
  for (a in arr){;}
}
alert("for(in)="+(new Date()-d));
d=new Date();
for (var i=0;i < 100;i++){
  for (var a=0,c;c=arr[a];a++){;}
}
alert("for(a,c;;)="+(new Date()-d));
d=new Date();
for (var i=0;i < 100;i++){
  var a=0;
  while(arr[a++]){;}
}
alert("while()="+(new Date()-d));

测试结果是(由快到慢):for(;;)<while ()<for(a,c)<for(in),前面几个的差距在小数量级的循环下可以接受,而for(in)所消耗的时间实在是不敢恭维。。。

其中,for(a,c)是我的教训。。。我在没有进行任何对比测试的时候,就偏信网上某贴上的评论,认为它的速度比for(;;)还快。。。唉。。。

最后,再测试一下多一个变量是否会进一步提升for(;;)的速度。

Language:  Javascript
var arr=new Array(1000).join(".;.").split(";");
var d=new Date();
for (var i=0;i < 1000;i++){
  for (var a=0;a < arr .length;a++){;}
}
alert("for(;;)="+(new Date()-d));
d=new Date();
var l=arr.length;
for (var i=0;i < 1000;i++){
  for (var a=0;a < l;a++){;}
}
alert("for(;l;)="+(new Date()-d));

还是有满明显的效率提升滴~~点击下面这个按钮实际查看它们的运算速度:

分享家:Addthis中国

Leave a comment for: "循环的效率"

*

Tag Cloud