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