What’s the fastest way to loop through an array in JavaScript?

What’s the fastest way to loop through an array in JavaScript?

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?

Solutions/Answers:

Solution 1:

After performing this test with most modern browsers…

http://jsben.ch/y3SpC

Currently, the fastest form of loop (and in my opinion the most syntactically obvious).

a standard for loop with length caching

for (var i = 0, len = myArray.length; i < len; i++) {

}

I would say this is definitely a case where I applaud JavaScript engine developers. A run time should be optimized for clarity, not cleverness.

Solution 2:

The absolute fastest way to loop through a javascript array is:

var len = arr.length;
while (len--) {
    // blah blah
}

See http://blogs.oracle.com/greimer/entry/best_way_to_code_a for a full comparison

Solution 3:

As of June 2016, doing some tests in latest Chrome (71% of the browser market in May 2016, and increasing):

  • 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.

I believe this thread is too old and it is misleading programmers to think they need to cache length, or use reverse traversing whiles with decrements to achieve better performance, writing code that is less legible and more prone to errors than a simple straightforward for loop. Therefore, I recommend:

  • 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]
    }
    

Solution 4:

If the order is not important, I prefer this style:

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

It caches the length and is much shorter to write. But it will iterate over the array in reverse order.

Related:  Randomize numbers with jQuery?

Solution 5:

It’s just 2018 so an update could be nice…

And I really have to disagree with the accepted answer.
It defers on different browsers. some do forEach faster, some for-loop, and some while
here is a benchmark on all method http://jsben.ch/mW36e

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

and since 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 = 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..in (only 3.3%)", () => {
  var ar = arr.slice(0,arr.length/33);
  for( const a in ar ) {
    var b = a + 1;
  }
}]
, ["Duff's device", () => {
  var i = 0;
  var r = arr.length % 8;
  var n = (arr.length - r) / 8;
  if (r > 0) do {
      var b = arr[i++] + 1;
    }
    while (--r);
  if (n > 0) do {
      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;
      i = --n >>> 3;
    }
    while (n);
}]
, ["Duff's device negative", () => {
  var r = arr.length % 8;
  var n = (arr.length-r) / 8; ///Math.floor(arr.length / 8);
  var i	= arr.length ; // -1;

  while(r){
    var b = arr[--i] + 1;
    --r;
  }

  while(n){
      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 j = arr[i-7] + 1;
      i = --n >>> 3;
  }
}]];
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>
Related:  Function declarations inside if/else statements?

Solution 6:

2014 While is back

Just think logical.

Look at this

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

 //do stuff

}
  1. Need to create at least 2 variables (index,length)
  2. Need to check if the index is smaller than the length
  3. Need to increase the index
  4. the for loop has 3 parameters

Now tell me why this should be faster than:

var length = array.length;

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

 //do stuff

}
  1. One variable
  2. No checks
  3. the index is decreased (Machines prefer that)
  4. while has only one parameter

I was totally confused when Chrome 28 showed that the for loop is faster than the while.
This must have ben some sort of

“Uh, everyone is using the for loop, let’s focus on that when
developing for chrome.”

But now, in 2014 the while loop is back on chrome. it’s 2 times faster , on other/older browsers it was always faster.

Lately i made some new tests. Now in real world envoirement those short codes are worth nothing and jsperf can’t actually execute properly the while loop, because it needs to recreate the array.length which also takes time.

Related:  JavaScript: Disable text selection via doubleclick

you CAN’T get the actual speed of a while loop on jsperf.

you need to create your own custom function and check that with window.performance.now()

And yeah… there is no way the while loop is simply faster.

The real problem is actually the dom manipulation / rendering time /
drawing time or however you wanna call it.

For example i have a canvas scene where i need to calculate the coordinates and collisions… this is done between 10-200 MicroSeconds (not milliseconds). it actually takes various milliseconds to render everything.Same as in DOM.

BUT

There is another super performant way using the for loop in some cases… for example to copy/clone an array

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

Notice the setup of the parameters:

  1. Same as in the while loop i’m using only one variable
  2. Need to check if the index is bigger than 0;
  3. As you can see this approach is different vs the normal for loop everyone uses, as i do stuff inside the 3th parameter and i also decrease directly inside the array.

Said that, this confirms that machines like the —

writing that i was thinking to make it a little shorter and remove some useless stuff and wrote this one using the same style:

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

Even if it’s shorter it looks like using i one more time slows down everything.
It’s 1/5 slower than the previous for loop and the while one.

Note: the ; is very important after the for looo without {}

Even if i just told you that jsperf is not the best way to test scripts .. i added this 2 loops here

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

And here is another answer about performance in javascript

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

This answer is to show performant ways of writing javascript. So if you can’t read that, ask and you will get an answer or read a book about javascript http://www.ecma-international.org/ecma-262/5.1/