基于javascript函数的迭代的替代方法(例如jQuery.each())

时间:2009-09-23 20:02:59

标签: javascript loops iteration

我一直在观看Google Tech Talks'Speed Up Your Javascript,在讨论循环时,发言者提到远离基于函数的迭代,例如jQuery.each()(等等,大约在24:05)在视频中)。他简要地解释了为什么要避免它们有意义,但不可否认,我不太清楚替代方案会是什么。比方说,在这种情况下,我想迭代一列表格单元格并使用该值来操纵相邻单元格的值(只是一个简单的例子)。任何人都可以解释并举例说明基于函数的迭代的替代方法吗?

5 个答案:

答案 0 :(得分:4)

如果你需要循环,只需一个简单的for循环就可以更快。

var l = collection.length;
for (var i = 0; i<l; i++) {
  //do stuff
} 

但是,仅仅因为它更快并不意味着它一直很重要。

这在客户端而不是服务器上运行,因此您不必担心使用用户数进行扩展,如果使用.each()快速进行扩展,则将其保留。但是,如果这很慢,for循环可以加快速度。

答案 1 :(得分:4)

Ye olde for-loop

答案 2 :(得分:2)

在我看来,基于函数的迭代会稍微慢一点,因为1)函数本身的开销,2)回调函数的开销被创建和执行N次,以及3)范围链中的额外深度。但是,我认为我会做一个快速的基准测试只是为了踢。事实证明,至少在我的简单测试案例中,基于函数的迭代更快。这是代码和发现

测试基准代码

// Function based iteration method
var forEach = function(_a, callback) {
  for ( var _i=0; _i<_a.length; _i++ ) {
    callback(_a[_i], _i);
  }
}

// Generate a big ass array with numbers 0..N
var a = [], LENGTH = 1024 * 10;
for ( var i=0; i<LENGTH; i++ ) { a.push(i); }

console.log("Array length: %d", LENGTH);

// Test 1: function-based iteration
console.info("function-base iteration");
var end1 = 0, start1 = new Date().getTime();

var sum1 = 0;
forEach(a, function(value, index) { sum1 += value; });

end1 = new Date().getTime();
console.log("Time: %sms; Sum: %d", end1 - start1, sum1);

// Test 2: normal for-loop iteration
console.info("Normal for-loop");
var end2 = 0, start2 = new Date().getTime();

var sum2 = 0;
for (var j=0; j<a.length; j++) { sum2 += a[j]; }

end2 = new Date().getTime();
console.log("Time: %sms; Sum: %d", end2 - start2, sum2);

每个测试只是简单地对数组进行求和,但在某种现实生活场景中可以实际看到。

FF 3.5的结果

Array length: 10240
function-base iteration
Time: 9ms; Sum: 52423680
Normal for-loop
Time: 22ms; Sum: 52423680

事实证明,在此测试用例中,基本的for迭代速度更快。我还没看过这个视频,但是我会看一看,看看他是否会在某处使基于函数的迭代变慢。

编辑:这绝不是最终的全部,只是一个引擎和一个测试用例的结果。我完全期望结果是另一种方式(基于函数的迭代变慢),但有趣的是看到某些浏览器如何进行优化(可能或可能不是专门针对这种类型的JavaScript),以便反之亦然。

答案 3 :(得分:1)

最快的迭代方法是减少你在循环中所做的事情。将内容从迭代中移除并最小化循环内的查找/增量,例如

var i = arr.length;

while (i--) {
   console.log("Item no "+i+" is "+arr[i]);
}

NB!通过测试最新的Safari(使用WebKit nightly),Chrome和Firefox,你会发现,如果它不是for each或{{{{}}},那么选择哪种循环并不重要1}}(或者更糟糕的是,任何基于它们的派生函数)。

另外,事实证明,以下for in循环比上述选项稍微快一点:

for

答案 4 :(得分:0)

如果循环的顺序无关紧要,那么下面应该是最快的,因为你只需要一个局部变量;另外,递减计数器和边界检查是用一个语句完成的:

var i = foo.length;
if(i) do { // check for i != 0
    // do stuff with `foo[i]`
} while(--i);

我通常使用以下内容:

for(var i = foo.length; i--; ) {
    // do stuff with `foo[i]`
}

它可能比以前的版本慢(后期与预先减少,for vs while),但更具可读性。