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

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

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

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

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

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


当前回答

截至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] }

其他回答

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

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

最快的方法是传统的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并提高了他的基准测试。

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

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

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

截至2017年9月,这些jsperf测试显示以下模式在Chrome 60上性能最佳:

function foo(x) {
 x;
};
arr.forEach(foo);

有人能繁殖吗?