我从书中学到,你应该这样写for循环:

for(var i=0, len=arr.length; i < len; i++){
    // blah blah
}

所以arr。每次不计算长度。

其他人说编译器会做一些优化,所以你可以这样写:

for(var i=0; i < arr.length; i++){
    // blah blah
}

我只是想知道在实践中哪种方法是最好的?


当前回答

截至2019年,WebWorker已经更加流行,对于大型数据集,我们可以使用WebWorker通过充分利用多核处理器来更快地处理。

我们还有Parallel.js,这使得WebWorker更容易用于数据处理。

其他回答

现在是2018年,所以更新一下会很好……

我真的不同意这个公认的答案。 它在不同的浏览器上有所不同。有的forEach更快,有的for循环,有的while 这里是所有方法的基准https://jsben.ch/mW36e

arr.forEach( a => {
  // ...
}

因为你可以看到很多for循环,比如for(a = 0;…)值得一提的是,如果没有'var',变量将被全局定义,这可能会极大地影响速度,因此它会变慢。

Duff's device run faster on opera but not in firefox var arr = arr = new Array(11111111).fill(255); var benches = [ [ "empty", () => { for(var a = 0, l = arr.length; a < l; a++); }] , ["for-loop", () => { for(var a = 0, l = arr.length; a < l; ++a) var b = arr[a] + 1; }] , ["for-loop++", () => { for(var a = 0, l = arr.length; a < l; a++) var b = arr[a] + 1; }] , ["for-loop - arr.length", () => { for(var a = 0; a < arr.length; ++a ) var b = arr[a] + 1; }] , ["reverse for-loop", () => { for(var a = arr.length - 1; a >= 0; --a ) var b = arr[a] + 1; }] ,["while-loop", () => { var a = 0, l = arr.length; while( a < l ) { var b = arr[a] + 1; ++a; } }] , ["reverse-do-while-loop", () => { var a = arr.length - 1; // CAREFUL do { var b = arr[a] + 1; } while(a--); }] , ["forEach", () => { arr.forEach( a => { var b = a + 1; }); }] , ["for const..in (only 3.3%)", () => { var ar = arr.slice(0,arr.length/33); for( const a in ar ) { var b = a + 1; } }] , ["for let..in (only 3.3%)", () => { var ar = arr.slice(0,arr.length/33); for( let a in ar ) { var b = a + 1; } }] , ["for var..in (only 3.3%)", () => { var ar = arr.slice(0,arr.length/33); for( var a in ar ) { var b = a + 1; } }] , ["Duff's device", () => { var len = arr.length; var i, n = len % 8 - 1; if (n > 0) { do { var b = arr[len-n] + 1; } while (--n); // n must be greater than 0 here } n = (len * 0.125) ^ 0; if (n > 0) { do { i = --n <<3; var b = arr[i] + 1; var c = arr[i+1] + 1; var d = arr[i+2] + 1; var e = arr[i+3] + 1; var f = arr[i+4] + 1; var g = arr[i+5] + 1; var h = arr[i+6] + 1; var k = arr[i+7] + 1; } while (n); // n must be greater than 0 here also } }]]; function bench(title, f) { var t0 = performance.now(); var res = f(); return performance.now() - t0; // console.log(`${title} took ${t1-t0} msec`); } var globalVarTime = bench( "for-loop without 'var'", () => { // Here if you forget to put 'var' so variables'll be global for(a = 0, l = arr.length; a < l; ++a) var b = arr[a] + 1; }); var times = benches.map( function(a) { arr = new Array(11111111).fill(255); return [a[0], bench(...a)] }).sort( (a,b) => a[1]-b[1] ); var max = times[times.length-1][1]; times = times.map( a => {a[2] = (a[1]/max)*100; return a; } ); var template = (title, time, n) => `<div>` + `<span>${title} &nbsp;</span>` + `<span style="width:${3+n/2}%">&nbsp;${Number(time.toFixed(3))}msec</span>` + `</div>`; var strRes = times.map( t => template(...t) ).join("\n") + `<br><br>for-loop without 'var' ${globalVarTime} msec.`; var $container = document.getElementById("container"); $container.innerHTML = strRes; body { color:#fff; background:#333; font-family:helvetica; } body > div > div { clear:both } body > div > div > span { float:left; width:43%; margin:3px 0; text-align:right; } body > div > div > span:nth-child(2) { text-align:left; background:darkorange; animation:showup .37s .111s; -webkit-animation:showup .37s .111s; } @keyframes showup { from { width:0; } } @-webkit-keyframes showup { from { width:0; } } <div id="container"> </div>

2014年While回来了

要有逻辑性。

看看这个

for( var index = 0 , length = array.length ; index < length ; index++ ) {

 //do stuff

}

需要创建至少2个变量(index,length) 需要检查索引是否小于长度 需要增加索引 for循环有3个参数

现在告诉我为什么这个要比

var length = array.length;

while( --length ) { //or length--

 //do stuff

}

一个变量 没有检查 指数下降(机器更喜欢这样) While只有一个参数

当Chrome 28显示for循环比while快时,我完全困惑了。 这一定是某种

“嗯,每个人都在使用for循环,让我们专注于这个 为铬开发。”

但是现在,在2014年,while循环又回到了chrome上。它快了2倍,在其他/旧浏览器上它总是更快。

最近我做了一些新的测试。现在在现实环境中,这些短代码毫无价值,jsperf实际上不能正确执行while循环,因为它需要重新创建数组。长度也需要时间。

你无法在jsperf上获得while循环的实际速度。

您需要创建自己的自定义函数,并使用window.performance.now()进行检查。

是的……while循环不可能简单地更快。

真正的问题实际上是dom操作/渲染时间 画图时间,随你怎么叫。

例如,我有一个画布场景,我需要计算坐标和碰撞…这是在10-200微秒(不是毫秒)之间完成的。它实际上需要不同的毫秒来渲染所有内容。和DOM中一样。

BUT

在某些情况下,还有另一种使用for循环的超级性能方式……例如复制/克隆一个数组

for(
 var i = array.length ;
 i > 0 ;
 arrayCopy[ --i ] = array[ i ] // doing stuff
);

注意参数的设置:

与while循环中一样,我只使用一个变量 需要检查索引是否大于0; 正如你所看到的,这种方法与每个人都使用的正常for循环不同,因为i在第3个参数内做东西,并且i也直接在数组内减少。

说到这里,这证实了机器喜欢

我想把它写得短一点,去掉一些无用的东西,用同样的风格写了这篇文章:

for(
 var i = array.length ;
 i-- ;
 arrayCopy[ i ] = array[ i ] // doing stuff
);

即使它更短,但再次使用i似乎会减慢一切。 它比之前的for循环和while循环慢了1/5。

注:;在没有{}的for looo后面非常重要

即使我只是告诉你,jsperf不是测试脚本的最佳方式。我在这里加了两个循环

http://jsperf.com/caching-array-length/40

这里有另一个关于javascript性能的答案

https://stackoverflow.com/a/21353032/2450730

这个答案是为了展示编写javascript的性能方法。所以如果你看不懂,问一下,你会得到答案,或者读一本关于javascript的书http://www.ecma-international.org/ecma-262/5.1/

截至2016年6月,在最新的Chrome上做了一些测试(2016年5月,浏览器市场份额为71%,并且还在增加):

The fastest loop is a for loop, both with and without caching length delivering really similar performance. (The for loop with cached length sometimes delivered better results than the one without caching, but the difference is almost negligible, which means the engine might be already optimized to favor the standard and probably most straightforward for loop without caching). The while loop with decrements was approximately 1.5 times slower than the for loop. A loop using a callback function (like the standard forEach), was approximately 10 times slower than the for loop.

我相信这个线程太旧了,它误导程序员认为他们需要缓存长度,或者使用反向遍历,同时递减来获得更好的性能,编写的代码不太容易读懂,更容易出错,而不是简单直接的for循环。因此,我建议:

If your app iterates over a lot of items or your loop code is inside a function that is used often, a straightforward for loop is the answer: for (var i = 0; i < arr.length; i++) { // Do stuff with arr[i] or i } If your app doesn't really iterate through lots of items or you just need to do small iterations here and there, using the standard forEach callback or any similar function from your JS library of choice might be more understandable and less prone to errors, since index variable scope is closed and you don't need to use brackets, accessing the array value directly: arr.forEach(function(value, index) { // Do stuff with value or index }); If you really need to scratch a few milliseconds while iterating over billions of rows and the length of your array doesn't change through the process, you might consider caching the length in your for loop. Although I think this is really not necessary nowadays: for (var i = 0, len = arr.length; i < len; i++) { // Do stuff with arr[i] }

在使用大多数现代浏览器执行此测试后: https://jsben.ch/wY5fo

目前,最快的循环形式(在我看来也是语法上最明显的)。

具有长度缓存的标准for循环

    var i = 0, len = myArray.length;
    while (i < len) {
        // your code
        i++
    }

我想说,这绝对是我为JavaScript引擎开发者喝彩的地方。运行时应该优化为清晰,而不是聪明。

现在是2017年。

我做了一些测试

https://jsperf.com/fastest-way-to-iterate-through-an-array/

看起来while方法在Chrome上是最快的。

看起来左边递减(——i)比Firefox上的其他递减(++i, i——,i++)快得多。

这种方法平均来说是最快的。但是它以相反的顺序迭代数组。

let i = array.length;
while (--i >= 0) {
    doSomething(array[i]);
}

如果前向顺序很重要,可以使用这种方法。

let ii = array.length;
let i = 0;
while (i < ii) {
    doSomething(array[i]);
    ++i;
}