319

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?

wong2
  • 34,358
  • 48
  • 134
  • 179
  • 2
    also worth a look when dealing with array looping: http://jsperf.com/array-loop-var-caching – cloakedninjas Jun 29 '12 at 09:12
  • @wong2 [Tthis benchmark](http://jsperf.com/browser-diet-jquery-each-vs-for-loop) from [Browserdiet](http://browserdiet.com/) has a more complete collection of alternatives. – Domi Jan 09 '14 at 12:26
  • 1
    http://jsben.ch/#/y3SpC – EscapeNetscape Oct 21 '16 at 08:47
  • Improved on the previous jsben: http://jsben.ch/#/R6LbS – Corbfon May 20 '17 at 20:32
  • Can we introduce the `for ... of` loop to this competition? The syntax seems even easier then a for loop without caching, and I want to know if I should switch to using for of loops. – programmerRaj Jun 19 '20 at 15:57
  • 1
    It looks like the answer is constantly changing and dependent on the engine. If you need speed, just go with a standard for loop and leave out all of the extra tricks. While these special tricks let you trade readability for slightly faster code today, the engines will continue to evolve, and the special tricks may become less effective, potentially even making your code slightly slower. – Scotty Jamison Feb 04 '21 at 20:09

25 Answers25

417

After performing this test with most modern browsers: https://jsben.ch/wY5fo

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

A standard for-loop with length caching

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

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

ib.
  • 27,830
  • 11
  • 80
  • 100
jondavidjohn
  • 61,812
  • 21
  • 118
  • 158
  • 7
    Interestingly, in IE9 this is faster: for (var i = 0, len = myArray.length; i < len; ++i) {} // prefix incr, instead of postfix – Christopher Bennage Oct 31 '11 at 17:38
  • 4
    See [Prefer prefix operators over postfix](http://thunderguy.com/semicolon/2002/08/13/prefer-prefix-operators-over-postfix/) for other reasons to use `++i`. – Bennett McElwee Nov 21 '11 at 08:28
  • 4
    I tested using prefix operator as @BennettMcElwee suggested and it runs a little faster: `for(var i=0, len=myArray.length; i – victmo Mar 22 '12 at 04:33
  • 30
    You have to be careful using this loop. I started using it and had a hard to track bug because of one mistake I made. If you nest two loops like this: http://jsfiddle.net/KQwmL/1/. You have to be careful to name the var len differently in the two loops, otherwise the second loop will overwrite the first len. – Rui Marques Nov 30 '12 at 13:08
  • 1
    why isn't the cached length written with "var len = myArray.length", wouldn't that avoid the scope clash? – Pete Sep 19 '13 at 10:34
  • 6
    @WillshawMedia You can declare multiple variables with a single `var` statement. How it is written, `len` is actually scoped as you suggest. – jondavidjohn Sep 19 '13 at 15:10
  • Oh of course, I do that all the time at the top of an object. Thanks! – Pete Sep 19 '13 at 15:15
  • That jsPerf link is broken, here's another : http://jsperf.com/array-length-vs-cached – UpTheCreek Oct 10 '13 at 11:39
  • 1
    The difference in performance seems negligible. Is it worth the loss in readability and subtle logic errors like what @RuiMarques ran in to? What if the array is modified within the loop and you were actually interested in the length of the array? A bug like that will sap many hours of programming time. – Josh Johnson Nov 22 '13 at 17:22
  • This answer is wrong. Source: http://stackoverflow.com/questions/1340589/javascript-are-loops-really-faster-in-reverse – Spencer Jun 08 '14 at 16:55
  • 2
    @Spencer You're wrong. Source: http://stackoverflow.com/a/7252102/555384 Ok, but in all seriousness, the blog this answer is based on is now 6 years old, you don't think JS Engine performance characteristics have changed? it has been the great arms race of our time. – jondavidjohn Jun 09 '14 at 16:56
  • 1
    @jondavidjohn Actually if you click on the jsperf linked in this answer you will see the while loop is much, much faster. This answer chose the second fastest (and quite a bit slower loop) because "it is the most syntactically obvious". The problem is that the question asks what is the fastest loop, not the fastest which also looks "obvious syntactically" whatever that subjectively means. – Spencer Jun 09 '14 at 17:48
  • that is not the fastest way -_- – EasyBB Dec 10 '14 at 01:10
  • In relation to this, what is the performance and difference with a for(var o in Object) – Ben Connor Hansell Apr 03 '15 at 21:51
  • It seems "while" can be useful sometimes https://jsperf.com/fastest-array-loops-in-javascript/32 – Federico Hernández Jan 13 '17 at 17:26
  • 1
    The `for of` loop method is only slightly slower than the index method but sometimes it is much clearer: http://jsben.ch/ervtW – Luke Miles Nov 09 '17 at 21:01
  • _A run time should be optimized for clarity, not cleverness_. Can you elaborate what does clarity offer over cleverness? Also this is not an optimization that affects behavior of program. – M.kazem Akhgary Dec 23 '17 at 08:07
  • 2
    http://jsben.ch/cMAc2 Improved the testcase, added forEach for comparison – Marcin Pevik Jan 30 '18 at 07:12
  • 1
    we can use the filters and map for the array traversing and it looks much more faster https://stackoverflow.com/questions/5349425/whats-the-fastest-way-to-loop-through-an-array-in-javascript/52928973#52928973 – Rigin Oommen Dec 04 '18 at 09:29
  • 1
    Also it's always best to get the length and save it to a variable instead of checking for each loop iteration. – Si8 Jul 22 '19 at 00:06
  • 1
    @jondavidjohn How is writing a "for-loop" with the `while` keyword "optimized for clarity"? – rinogo Mar 11 '21 at 20:26
  • 1
    It's 2021 and it this still valid ? What about functions like map ? – Tharindu Thisarasinghe May 23 '21 at 19:39
  • 2
    @TharinduThisarasinghe This will always be valid. No more efficient expression exists in any language. Technically ++i (using the prefix operator) is faster because it saves the computer from copying the integer (note that with such small ints, this would ever make a difference). In response to the question about map, functional patterns are almost always slower. In the case of map, all object have to be copied. Just such an iteration by itself, like forEach, is much much slower than a for or while loop. Creating a function closure, and copying arguments also slows the usage of such. – Hunter Kohler Jun 06 '21 at 02:25
  • This answer must be outdated by now, consider upvoting the more recent answers. – 6infinity8 Jun 25 '21 at 07:43
  • 1
    This answer advocates a for loop and yet shows a while loop as an example. – Greggory Wiley Feb 14 '23 at 03:55
  • But this is a while loop not a for loop, right? You state for loop and then proceed to use a while loop? – Syed M. Sannan Aug 29 '23 at 07:10
108

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

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

See this post for a full comparison

Sᴀᴍ Onᴇᴌᴀ
  • 8,218
  • 8
  • 36
  • 58
gnur
  • 4,671
  • 2
  • 20
  • 33
  • 1
    Don’t forget to use `var` (else `len` becomes a global variable). Also, see http://jsperf.com/loops for more loop benchmarks. – Mathias Bynens Mar 18 '11 at 11:20
  • 30
    The blog post this answer is based on is now almost 4 years old, and a lot has changed in js engines in that time, see my answer below for an updated comparison. – jondavidjohn Aug 31 '11 at 03:01
  • 2
    I agree with @jondavidjohn. I tested this code and it turned out to be the less efficient... Check jsperf.com/caching-array-length/84 – victmo Mar 22 '12 at 04:38
  • 2
    The above answer is almost universally (across browsers) much much slower than a for-loop. See the JSPerf link in accepted answer. It is a great shame, cause it's extremely readable IMO. – Letharion Apr 15 '13 at 12:49
  • @LeviMorrison "this structure works only for positive values of len" and the other for-loop examples do? – valbaca Jun 09 '13 at 20:21
  • @gnur The loop body seems to be empty. Reverting your loop is usually a bad idea due to caching concerns. See [this benchmark](http://jsperf.com/browser-diet-jquery-each-vs-for-loop) for consideration. – Domi Jan 09 '14 at 12:25
  • This should be the accepted answer. The accepted answer is wrong. Source: http://stackoverflow.com/questions/1340589/javascript-are-loops-really-faster-in-reverse – Spencer Jun 08 '14 at 16:55
  • This is best practise. –  Jun 12 '16 at 16:27
  • 3
    Im guessing @jondavidjohn that what you mean by 'my answer below' is 'my answer above' lol. – Shanimal Dec 28 '16 at 00:47
63

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]
    }
    
CGodo
  • 1,478
  • 14
  • 15
  • 1
    Nope. http://jsbench.github.io/#67b13d4e78cdd0d7a7346410d5becf12 shows that the fastest is "Reverse loop, implicit comparison, inlined code" (105,221 ops/sec) while "Loop, cached value, inlined code" scored only 76,635 ops/sec (Chrome 38.0.2125.111) – Fr0sT Feb 14 '17 at 11:30
  • @Fr0sT Your benchmark is a different scenario, traversing arrays from index 1 to <= length. Of course this is going to lead to different results. If you try traversing zero-based arrays with < length -- which seems to me it is the usual scenario -- you'll discover that the results are better optimized with a normal "for" loop (with cached length being slightly faster). – CGodo Feb 27 '17 at 14:53
  • Kyopaxa changed benchmarks to (0 <= i < length), results are the same. "Reverse loop, implicit comparison, function call" scored 365 kops/sec, while "Loop, cached value, inlined code" scored 350 kops/sec (FF 51) – Fr0sT Feb 28 '17 at 07:23
  • @Fr0sT if you change the zero-based cached for-loops with no equal comparison, such as `for(let i=0, j=array.length; i < j; i++)`, the forward for loops speed up considerably. On a few tests I ran it won, on most it was within the margin of error or the reverse loop. – Isaac B Mar 02 '17 at 02:49
  • 1
    @IsaacB and all, sorry I didn't notice that the bench is quite incorrect - all direct loops iterate 1..length while reverse loops iterate length..0 (arr[length] item is invalid). I fixed the tests and now they show the following results: "Loop, inlined code" 360,616 ops/sec ±0.27%, "Loop, cached value, inlined code" 345,786 ops/sec ±2.18% (Sic!) "Reverse loop, implicit comparison, inlined code" 322,640 ops/sec ±2.90% (!!!). Tests were executed by FF51. New bench is here http://jsbench.github.io/#6bdfcd2692ba80c16a68c88554281570. So it seems it's no sense in uglifying the loops. – Fr0sT Mar 02 '17 at 08:07
  • Interesting that Chrome 56.0.2924.87 has performance **nearly five times worse** than FF 51 in this test (~77 vs ~360 kops/sec)! – Fr0sT Mar 02 '17 at 08:21
  • `++i` instead will probably scratch off a few more milliseconds.. just sayen – Leathan Aug 09 '17 at 14:14
  • I have readability requirements (arrays referenced as a specific item in a complex JSON object) and I find the `forEach` options very helpful. – zeroquaranta Sep 14 '17 at 10:54
  • @Fr0sT yeah, I've been noticing Firefox *kills* Chrome in most of the jspref tests I've run. – Daniel Sokolowski Aug 17 '18 at 01:59
59

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

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

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

and since you can see a lot of for-loops like for(a = 0; ... ) then it's worth to mention that without 'var', variables will be defined globally and this can dramatically affect speed so it'll get slow.

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>
nullqube
  • 2,959
  • 19
  • 18
  • 3
    @Maykonn you probably wanted to say "and it works everywhere but Opera Mini" – dube Aug 25 '18 at 18:55
  • 4
    @Maykonn Which is not listed in the default view because 0.18% of all users have IE8 and you should not waste time trying to support it; in 2018 it's a dead horse. – dube Aug 27 '18 at 06:35
  • 1
    It is definitely true if you consider all users around the world. But, unfortunately, in specific parts of the world IE8 is relevant yet. – Maykonn Aug 27 '18 at 14:49
  • 1
    If I may, not only different browsers will have different results with different methods, but same browsers will have different results with different inputs. A huge Number only Array will be very optimized, while a small mixed one won't. – Kaiido Mar 20 '19 at 14:24
  • 1
    How about for..of and for..in? – Tahlil Jun 19 '19 at 12:11
  • 1
    @Tahlil Thanks . – nullqube Jun 19 '19 at 20:35
  • Why would you do >for( const a in ar ) {< it doesn't gain anything more than `let` or `var`? – Sapphire_Brick Sep 11 '19 at 23:04
  • Those Duff's devices are bugged. They won't loop though all elements. If you sum up all the array numbers it won't return the same result as the others. – Jorge Fuentes González Jun 15 '20 at 17:36
  • One gotcha with the forEach loop to be careful/aware of is using async/await (asynchronous code). forEach will not wait for promises to be resolved unlike a traditional for-loop. If you want all promises to be resolved before executing the next statement after the loop, do not use forEach. Coder beware. – Greg R Taylor Apr 29 '22 at 02:16
45

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.

Felix Kling
  • 795,719
  • 175
  • 1,089
  • 1,143
21

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.

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/

Community
  • 1
  • 1
cocco
  • 16,442
  • 7
  • 62
  • 77
  • This answer starts of *very good*. I to noticed that the last couple of years the `for` was faster then the `while`, and I once read on crome-dev it was exactly because of the reason you mention. It would be just a matter of time before `while` would catch up again. From that point on, the logic in the first part of your answer *will hold* (once again, yay)! **However** Modern implementations no longer rigidly follow every ecma-specified step (they optimize). Since now your engine is no longer the most noticeable bottle-neck, one can now actually notice the *CPU cache-misses in reverse loops*! – GitaarLAB Mar 17 '15 at 21:32
  • Explain, so maybe i can correct the answer or learn something new. btw the answer is now more than a year old ... browsers may have changed over time as they always do... – cocco Aug 18 '15 at 13:02
  • In my opinion, while( --length ) is evil because while it technically works because 0 is false, 0 and false aren't really truly the same thing semantically speaking. – scott.korin Oct 14 '15 at 13:02
  • yeah... it's an older post now... but yeah i love the simplicity of while. And for sure as you mention it in both cases you need to know what to write. At the other side i never had the necessity to loop trough negative numbers. – cocco Oct 14 '15 at 13:05
  • I laughed way too hard at the previous comment – YenForYang Sep 09 '18 at 06:21
  • 1
    Be careful, `index--` will evaluate to `false` when `index` is `0`, which you don't want if you're iterating over everything in an array – Toni Leigh Jan 28 '20 at 14:18
10

"Best" as in pure performance? or performance AND readability?

Pure performance "best" is this, which uses a cache and the ++prefix operator (my data: http://jsperf.com/caching-array-length/189)

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

I would argue that the cache-less for-loop is the best balance in execution time and programmer reading time. Every programmer that started with C/C++/Java won't waste a ms having to read through this one

for(var i=0; i < arr.length; i++){
  // blah blah
}
valbaca
  • 625
  • 6
  • 12
  • 3
    +1 for readability. No matter how well `len` is named, one would always have to do a double take on that first loop. The second loop's intention is obvious. – Josh Johnson Nov 22 '13 at 17:24
10

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

The latest revision of test, which I prepared (by reusing older one), shows one thing.

Caching length is not that much important, but it does not harm.

Every first run of the test linked above (on freshly opened tab) gives best results for the last 4 snippets (3rd, 5th, 7th and 10th in charts) in Chrome, Opera and Firefox in my Debian Squeeze 64-bit (my desktop hardware). Subsequent runs give quite different result.

Performance-wise conclusions are simple:

  • Go with for loop (forward) and test using !== instead of <.
  • If you don't have to reuse the array later, then while loop on decremented length and destructive shift()-ing array is also efficient.

tl;dr

Nowadays (2011.10) below pattern looks to be the fastest one.

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

Mind that caching arr.length is not crucial here, so you can just test for i !== arr.length and performance won't drop, but you'll get shorter code.


PS: I know that in snippet with shift() its result could be used instead of accessing 0th element, but I somehow overlooked that after reusing previous revision (which had wrong while loops), and later I didn't want to lose already obtained results.

przemoc
  • 3,759
  • 1
  • 25
  • 29
  • Creating variable insite the loop like let current = arr[i] can reduce a performance (big memory allocation)? Or would be better to declare current before the loop? Or use arr[i] in all places inside the loop? – Makarov Sergey Jul 18 '19 at 05:29
  • Declare any variables that the loop is going to use before the loop – sjjk001 May 04 '21 at 15:14
8

**cache the array length inside the loop ,some seconds of time will be eluded . Depends on the items in the array if there are more items in array there is major difference with respect to Ms of time*

**

sArr; //Array[158];

for(var i = 0 ; i <sArr.length ; i++) {
 callArray(sArr[i]); //function call
}

***end: 6.875ms***

**

**

sArr; //Array[158];
for(var i = 0,len = sArr.length ; i < len ; i++) {
  callArray(sArr[i]); //function call
}

***end: 1.354ms***

**

Shushanth Pallegar
  • 2,832
  • 1
  • 14
  • 16
7

This looks to be the fastest way by far...

var el;
while (el = arr.shift()) {
  el *= 2;
}

Take into account that this will consume the array, eating it, and leaving nothing left...

Sergio
  • 28,539
  • 11
  • 85
  • 132
  • 2
    `arr.shift();` instead of `arr.pop()` so that array reverse can be avoided. – Tintu C Raju Oct 22 '15 at 05:19
  • 1
    @Gargaroz if you are getting a JSON from a webservice for example a chat service or items on a product catalog. Another situation when you just need to use the array once can be for example a chart that gets many coordinates on a intervall basis. There are many examples. – Sergio Feb 18 '16 at 17:53
  • Cool, thank you for the explanation, very kind of you; can you point me in the direction where I may find further examples to exploit this kind of loop? – Gargaroz Feb 22 '16 at 08:52
  • 2
    Currently in Chrome 53 and Firefox 48 it's one of the slowest approach - check on [perfjs.info/array-iteration](http://perfjs.info/#!/2DDD96CD-1F90-4792-9CE8-D6CA07CFC248) – Pencroff Sep 15 '16 at 22:31
  • 1
    @Alireza agree, I have a comment for that in my answer also. – Sergio Apr 12 '17 at 08:55
4

It's the year 2017.

I made some tests.

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

Looks like the while method is the fastest on Chrome.

Looks like the left decrement (--i) is much faster than the others (++i, i--, i++) on Firefox.

This approach is the fasted on average. But it iterates the array in reversed order.

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

If the forward order is important, use this approach.

let ii = array.length;
let i = 0;
while (i < ii) {
    doSomething(array[i]);
    ++i;
}
SeregPie
  • 1,223
  • 1
  • 18
  • 20
  • 3
    **By using the keyword `let` you are actually comparing scope creation performance instead of loop performance.** Using `let i = 0, ii = array.length` in your `for` loops will create a new scope for those variables inside the `for` block. Your `while` examples do not create a new scope for the variables inside the `while` block and that's why they are faster. If you use `var` instead of `let` in your for loops, you'll see how for loops are still as fast as whiles in 2017, but more readable. – CGodo Jun 05 '17 at 18:42
  • Here is a jsperf of what I am talking about: https://jsperf.com/javascript-loop-testing-let-vs-var – CGodo Jun 05 '17 at 18:50
  • This is only an issue in Chrome. In other Browsers `var` and `let` have the same performance - https://stackoverflow.com/a/32345435/1785975 – SeregPie Jun 10 '17 at 19:00
  • Interesting. Anyways, I don't find the statement of "`while` being faster in Chrome" accurate. It's only if using `let` due to performance issues of that keyword in Chrome. If using `var` or with other browsers, `for` and `while` are pretty much the same, sometimes `for` is even faster depending of the benchmark, and it is more compact and readable imho. – CGodo Jun 11 '17 at 09:03
3

I have a test all way in here. Check this! https://gist.github.com/DungGramer/7efdfefecaa1b8f5d6510202524dc751

My result:

  • pop is fastest, forEach is goodest for readable and fast
  • do..while faster than for
  • loop faster if no have condition (like if)
  • --i is fastest
DungGramer
  • 177
  • 10
  • Your code is incorrect for `pop`. `arrClone` is empty when you try to iterate it – episage Dec 04 '22 at 09:59
  • I made an updated version over here: https://gist.github.com/episage/076ded007d0583f6a275f93a8c9c8047 . `for ++` wins for large arrays. – episage Dec 04 '22 at 10:33
2

I'm always write in the first style.

Even if a compiler is smart enough to optimize it for arrays, but still it smart if we are using DOMNodeList here or some complicated object with calculated length?

I know what the question is about arrays, but i think it is a good practice to write all your loops in one style.

Olegas
  • 10,349
  • 8
  • 51
  • 72
1
var arr = []; // The array
var i = 0;
while (i < arr.length) {
    // Do something with arr[i]
    i++;
}

i++ is faster than ++i, --i and i--

Also, you can save the last line doing arr[i++] the last time you need to access i (but this can be hard to debug).

You can test it here (with other loop tests): http://jsperf.com/for-vs-whilepop/5

Forestrf
  • 364
  • 7
  • 13
  • 1
    Currently in Chrome 53 it's true, but Firefox 48 has the same speed - check on [perfjs.info/array-iteration](http://perfjs.info/#!/2DDD96CD-1F90-4792-9CE8-D6CA07CFC248) – Pencroff Sep 15 '16 at 22:32
  • https://thunderguy.com/semicolon/2002/08/13/prefer-prefix-operators-over-postfix/ says `++i` is faster... – IMTheNachoMan Dec 19 '19 at 15:33
1

As of September 2017 these jsperf tests are showing the following pattern to be most performant on Chrome 60:

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

Is anyone able to reproduce?

John Vandivier
  • 2,158
  • 1
  • 17
  • 23
  • Yes it seems to be fastest, However try running this in IE11 and those options are the slowests. And in Firefox 55.03 the 'old busted cached len' is getting to 12mil, a staggering performance compared to the 3.3k of chrome. To be consistent in performance in all browsers you should use the fastest average loop for every browser. – Plippie Oct 03 '17 at 09:23
1

Fastest approach is the traditional for loop. Here is a more comprehensive performance comparison.

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

1

If you want a faster for loop, define your variables outside the loop and use below syntax

  const iMax = lengthOftheLoop;
  var i = 0;
  for (; i < iMax; i++) {
    console.log("loop"+i);
  }

reference: https://medium.com/kbdev/voyage-to-the-most-efficient-loop-in-nodejs-and-a-bit-js-5961d4524c2e

User123456
  • 2,492
  • 3
  • 30
  • 44
1

although it is a very old question, it is a very interesting one,

pardon me for tweaking the question a little bit but I am going to answer it at the end.

the question made me ask myself if there are any better methods for looping in js:

so I have made some tests and here is what I found out: enter image description here

for 1000_000 record: the best is forEach.

for 100 records: it simply doesn't matter.


to go back to your question:

the example i created is not exactly like the question .. but i found out some interesting things:

firstly : like what you said , the arr.length will evaluate every time if it is within the comparison statement i < arr.length ...

note : the variable of arrLength below is not more than the a number of 1000_000 records..

enter image description here

for instance : this wont work enter image description here

but this will

enter image description here

and it will take .036 seconds .. which is very large compared to what it takes if the number was constant...


to sum up,

it is better to use FOREACH

in your case: the i<arr.length should take more time ( around 1.3 the usual)

see the tests : see the tests

Ahmed Mansour
  • 500
  • 4
  • 14
1
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   │
└─────────┴───────────────────────┴────────────┴──────────┘

Tested on Macbook Air M1 2020. NodeJS 18.

For arrays with 10_000_000 elements, the standard for loop wins. For other cases see my gist: https://gist.github.com/episage/076ded007d0583f6a275f93a8c9c8047#file-result-txt

Shoutout to @DungGramer. I fixed bugs and enhanced his benchmark.

episage
  • 1,802
  • 1
  • 11
  • 7
0

I have tried some other ways to iterate a huge array and found out that halving the array length and then iterating both halves in a single loop is faster. This performance difference can be seen while processing huge arrays.

var firstHalfLen =0;
var secondHalfLen = 0;
var count2=0;
var searchterm = "face";
var halfLen = arrayLength/2;
if(arrayLength%2==halfLen)
{
   firstHalfLen = Math.ceil(halfLen);
   secondHalfLen=Math.floor(halfLen);
}
else
{
   firstHalfLen=halfLen;
   secondHalfLen=halfLen;
}
for(var firstHalfCOunter=0,secondHalfCounter = arrayLength-secondHalfLen;
    firstHalfCOunter < firstHalfLen;
    firstHalfCOunter++)
{
  if(mainArray[firstHalfCOunter].search(new RegExp(searchterm, "i"))> -1)
  {
    count2+=1;
  }
  if(secondHalfCounter < arrayLength)
  {
    if(mainArray[secondHalfCounter].search(new RegExp(searchterm, "i"))> -1)
    {
        count2+=1;
    }
    secondHalfCounter++; 
  }
}

Some performance comparison (using timer.js) between the cached length for-loop VS the above method.

http://jsfiddle.net/tejzpr/bbLgzxgo/

tejzpr
  • 945
  • 8
  • 19
0

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?

Moritz Schmitz v. Hülst
  • 3,229
  • 4
  • 36
  • 63
  • 3
    If you do `while (i--)` then the truthfulness of `i` will be tested before decrementing rather than decrementing and then testing truthfulness. – Justin Fisher Apr 02 '15 at 02:40
0

A basic while loop is often the fastest. jsperf.com is a great sandbox to test these types of concepts.

https://jsperf.com/fastest-array-loops-in-javascript/24

Devappended
  • 104
  • 2
-2

The most elegant solution I know of is using map.

var arr = [1,2,3];
arr.map(function(input){console.log(input);});
Dan
  • 1,179
  • 2
  • 10
  • 18
-2

Try this:

var myarray =[],
i = myarray.lenght;
while(i--){
// do somthing
}
U13-Forward
  • 69,221
  • 14
  • 89
  • 114
li bing zhao
  • 1,388
  • 13
  • 12
-3

It is late 2022

Sometimes is ineffective calculate with array length at all:

If you have an array with indexes var myArray = [1,2,3,4,25,999999999999] it is very slow to use any solution which is going trough array with increasing index by one (including forEach).

Best solution for me, and it is not mentioned in any top-voted answer is:

for(let _i in myArray ) {
   if(myArray[_i]) {
     (function(s) {
        ///
     })(myArray[_i]) 
   }
}
Martin
  • 2,575
  • 6
  • 32
  • 53
  • This is a very bad recommendation. The `for...in` construct loops over the enumerable properties of an object. This is very different from iterating the elements of an array, has no guaranteed order, will include the `length` property, and will likely lead to worse performance. It's simply not meant to be used for array iteration. Furthermore, the code you wrote will only run the inner function for the enumerable properties whose values are truthy. – Domino Oct 16 '22 at 09:58
  • in practice array where idex should be DB ID of some sql/REDIS result for example, IDS are never go through some logical order and array indexes always looks like [545656,42165456,445445454] and there i dont know faster solution. Please recomend some. Anyway any loop using increasing index is unusalbe took 5 sec with array of 2 items usinng indexes [10,985682] and array.length is always 985683 in this case. – Martin Oct 17 '22 at 10:22
  • "the code you wrote will only run the inner function for the enumerable properties whose values are truthy" <- yes thats what meant to do that, why work with null or undefined .. results? – Martin Oct 17 '22 at 10:23
  • And yes it worth to use indexes as bearer of information like USER ID, you can access user data very fast, or chceck if user is in your data chunk. Any other solution to check by ID stored as multidimensional value is extremely prefirmance ineffective and reprosuces rpoblem wit going trough long arrays even more. And more, JSON converted to array sometimes must be Object and sometimes not, it depends on data returned which is unpredicable. – Martin Oct 17 '22 at 10:31
  • If you have a *sparse array*, that is to say an array which doesn't actually contain elements for every index, use the the [forEach](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/forEach) method. With that said, you really should avoid creating sparse arrays in the first place. – Domino Oct 18 '22 at 00:26
  • It's also possible for an array to contain the values null or undefined, the number 0, the empty string and the boolean false, and for you to want to perform something with these values. The code you provided without explanations is not generic and does not provide an answer to this SO question. – Domino Oct 18 '22 at 00:32
  • But not matter the situation, using the `for .. in` construct to iterate over an array is plain wrong. – Domino Oct 18 '22 at 00:33