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

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

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

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

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

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


当前回答

另一个jsperf.com测试:http://jsperf.com/while-reverse-vs-for-cached-length

反向while循环似乎是最快的。唯一的问题是while(——i)将停止于0。我怎么能访问数组[0]在我的循环那么?

其他回答

我在这里有个测试。检查这个! https://gist.github.com/DungGramer/7efdfefecaa1b8f5d6510202524dc751

我的结果:

pop是最快的,forEach的可读性和速度最好 while比for快 如果没有条件,循环更快(如if) i是最快的

现在是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>

如果顺序不重要,我更喜欢这种风格:

for(var i = array.length; i--; )

它缓存了长度,写起来要短得多。但是它会以相反的顺序遍历数组。

最快的方法是传统的for循环。这里有一个更全面的性能比较。

https://gists.cwidanage.com/2019/11/how-to-iterate-over-javascript-arrays.html

Benchmarking [10000000] element array...
The fastest [for ++] took [76762166ns]
┌─────────┬───────────────────────┬────────────┬──────────┐
│ (index) │         type          │  time[ns]  │ baseline │
├─────────┼───────────────────────┼────────────┼──────────┤
│    0    │       'for ++'        │  76762166  │    1     │
│    1    │       'for of'        │  82407583  │   1.07   │
│    2    │   '--while forward'   │  83723083  │   1.09   │
│    3    │ 'do while forward --' │  83942958  │   1.09   │
│    4    │ '--do while forward'  │  84225584  │   1.1    │
│    5    │  'while forward --'   │  85156957  │   1.11   │
│    6    │    '--while >= 0'     │  89745916  │   1.17   │
│    7    │     '++ do while'     │  90306542  │   1.18   │
│    8    │     'for !== ++'      │  90319083  │   1.18   │
│    9    │       '-- for'        │  90360167  │   1.18   │
│   10    │   'for i length --'   │  90558833  │   1.18   │
│   11    │       '++ for'        │  90616125  │   1.18   │
│   12    │     'do while ++'     │  90657541  │   1.18   │
│   13    │   '--for i length'    │  90757708  │   1.18   │
│   14    │       'for --'        │  90799875  │   1.18   │
│   15    │      '++ while'       │  92697417  │   1.21   │
│   16    │     '++ for !=='      │  94488209  │   1.23   │
│   17    │         'pop'         │ 108399917  │   1.41   │
│   18    │      'while ++'       │ 109276500  │   1.42   │
│   19    │    'forEach call'     │ 147140124  │   1.92   │
│   20    │       'forEach'       │ 148886207  │   1.94   │
│   21    │         'map'         │ 207100583  │   2.7    │
│   22    │     'Array from'      │ 353166207  │   4.6    │
│   23    │       'flatMap'       │ 1213152082 │   15.8   │
│   24    │   'Object.keys map'   │ 1294475333 │  16.86   │
│   25    │       'for in'        │ 1338988749 │  17.44   │
└─────────┴───────────────────────┴────────────┴──────────┘

在Macbook Air M1 2020上测试。NodeJS 18。

对于包含10_000_000个元素的数组,循环标准胜出。关于其他情况,请参阅我的要点:https://gist.github.com/episage/076ded007d0583f6a275f93a8c9c8047#file-result-txt

大声喊出@DungGramer。我修复了bug并提高了他的基准测试。