What's the fastest way to loop through an arra

2019-01-01 07:58发布

I learned from books that you should write for loop like this:

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

so the arr.length will not be calculated each time.

Others say that the compiler will do some optimization to this, so you can just write:

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

I just want to know which is the best way in practice?

21条回答
心情的温度
2楼-- · 2019-01-01 08:46

It's just 2018 so an update could be nice...

And I really have to disagree with the accepted answer. here is a benchmark on all method http://jsben.ch/mW36e

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

and sice you can see alot of for-loop like for(a = 0; ... ) then worth to mention that without 'var' variables will be define globally and this can dramatically affects on speed so it'll get slow.

var arr = new Array(11111111).fill().map((_,n)=>n);
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;
  });
}]];
function bench(title, f) {
  var t0 = performance.now();
  var res = f();
  return performance.now() - t0;   // console.log( `${title} took ${t1-t0} millisec` );
}
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( a => [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) => {
  return  `<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;
}
<div id="container"> </div>

查看更多
其实,你不懂
3楼-- · 2019-01-01 08:47

The faster way to loop in an array is by using the filter. The filter() method creates a new array with all elements that pass the test implemented by the provided function.

https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/filter

const words = ['Floccinaucinihilipilification', 'limit', 'elite', 'Hippopotomonstrosesquipedaliophobia', 'destruction', 'present'];

const result = words.filter(word => word.length > 6);

console.log(new Date(), result);

From my experience, I always prefer filters, map etc..

查看更多
余生请多指教
4楼-- · 2019-01-01 08:49

Another jsperf.com test: http://jsperf.com/while-reverse-vs-for-cached-length

The reverse while loop seems to be the fastest. Only problem is that while (--i) will stop at 0. How can I access array[0] in my loop then?

查看更多
登录 后发表回答