What's the fastest way to loop through an array in JavaScript?
Asked Answered
N

25

320

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?

Naxos answered 18/3, 2011 at 8:5 Comment(6)
also worth a look when dealing with array looping: jsperf.com/array-loop-var-cachingInterminable
@Naxos Tthis benchmark from Browserdiet has a more complete collection of alternatives.Milreis
jsben.ch/#/y3SpCSlantwise
Improved on the previous jsben: jsben.ch/#/R6LbSCanton
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.Homecoming
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.Apparent
D
420

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.

Debility answered 31/8, 2011 at 3:0 Comment(26)
Interestingly, in IE9 this is faster: for (var i = 0, len = myArray.length; i < len; ++i) {} // prefix incr, instead of postfixVallejo
See Prefer prefix operators over postfix for other reasons to use ++i.Mauromaurois
I tested using prefix operator as @BennettMcElwee suggested and it runs a little faster: for(var i=0, len=myArray.length; i<len; ++i) Check jsperf.com/caching-array-length/84Medullated
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: 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.Disherison
why isn't the cached length written with "var len = myArray.length", wouldn't that avoid the scope clash?Antalkali
@WillshawMedia You can declare multiple variables with a single var statement. How it is written, len is actually scoped as you suggest.Debility
Oh of course, I do that all the time at the top of an object. Thanks!Antalkali
That jsPerf link is broken, here's another : jsperf.com/array-length-vs-cachedKinnard
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.Roxi
This answer is wrong. Source: #1341089Inclined
@Inclined You're wrong. Source: https://mcmap.net/q/36231/-what-39-s-the-fastest-way-to-loop-through-an-array-in-javascript 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.Debility
@Debility 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.Inclined
that is not the fastest way -_-Tawana
In relation to this, what is the performance and difference with a for(var o in Object)Tupler
It seems "while" can be useful sometimes jsperf.com/fastest-array-loops-in-javascript/32Ankney
The for of loop method is only slightly slower than the index method but sometimes it is much clearer: jsben.ch/ervtWAbut
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.Pratt
jsben.ch/cMAc2 Improved the testcase, added forEach for comparisonSuperego
we can use the filters and map for the array traversing and it looks much more faster #5349925Immure
Also it's always best to get the length and save it to a variable instead of checking for each loop iteration.Parton
@Debility How is writing a "for-loop" with the while keyword "optimized for clarity"?Helainehelali
It's 2021 and it this still valid ? What about functions like map ?Shandy
@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.Genip
This answer must be outdated by now, consider upvoting the more recent answers.Swayne
This answer advocates a for loop and yet shows a while loop as an example.Assam
But this is a while loop not a for loop, right? You state for loop and then proceed to use a while loop?Moria
C
112

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

Contrite answered 18/3, 2011 at 8:13 Comment(9)
Don’t forget to use var (else len becomes a global variable). Also, see jsperf.com/loops for more loop benchmarks.Capybara
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.Debility
I agree with @jondavidjohn. I tested this code and it turned out to be the less efficient... Check jsperf.com/caching-array-length/84Medullated
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.Slog
@LeviMorrison "this structure works only for positive values of len" and the other for-loop examples do?Hipolitohipp
@Contrite The loop body seems to be empty. Reverting your loop is usually a bad idea due to caching concerns. See this benchmark for consideration.Milreis
This should be the accepted answer. The accepted answer is wrong. Source: #1341089Inclined
This is best practise.Denison
Im guessing @Debility that what you mean by 'my answer below' is 'my answer above' lol.Stroup
V
65

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]
    }
    
Versieversification answered 18/6, 2016 at 16:5 Comment(9)
Nope. 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)Calces
@Calces 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).Versieversification
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)Calces
@Calces 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.Coccyx
@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 jsbench.github.io/#6bdfcd2692ba80c16a68c88554281570. So it seems it's no sense in uglifying the loops.Calces
Interesting that Chrome 56.0.2924.87 has performance nearly five times worse than FF 51 in this test (~77 vs ~360 kops/sec)!Calces
++i instead will probably scratch off a few more milliseconds.. just sayenEsta
I have readability requirements (arrays referenced as a specific item in a complex JSON object) and I find the forEach options very helpful.Auto
@Calces yeah, I've been noticing Firefox kills Chrome in most of the jspref tests I've run.Rant
F
60

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>
Footpad answered 5/3, 2018 at 8:11 Comment(8)
@Maykonn you probably wanted to say "and it works everywhere but Opera Mini"Andres
@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.Andres
It is definitely true if you consider all users around the world. But, unfortunately, in specific parts of the world IE8 is relevant yet.Vigue
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.Henghold
How about for..of and for..in?Emileeemili
Why would you do >for( const a in ar ) {< it doesn't gain anything more than let or var?Carrot
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.Shawndashawnee
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.Womanhater
E
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.

Eloiseloisa answered 18/3, 2011 at 8:15 Comment(3)
You just killed it.Dematerialize
don't you need i >= 0;?Cache
@MarwaAhmad: No. i-- returns a number and once the number is 0 the condition is false because Boolean(0) === false.Eloiseloisa
O
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://mcmap.net/q/36392/-how-to-39-minify-39-javascript-code

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/

Oestradiol answered 2/6, 2014 at 15:58 Comment(5)
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!Savick
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...Oestradiol
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.Stentor
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.Oestradiol
Be careful, index-- will evaluate to false when index is 0, which you don't want if you're iterating over everything in an arrayMoppet
S
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.

Spindly answered 17/10, 2011 at 15:47 Comment(2)
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?Mozambique
Declare any variables that the loop is going to use before the loopVambrace
H
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
}
Hipolitohipp answered 9/6, 2013 at 20:54 Comment(1)
+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.Roxi
T
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***

**

Tenor answered 10/11, 2014 at 19:31 Comment(0)
I
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...

Inoculum answered 18/6, 2015 at 22:45 Comment(5)
arr.shift(); instead of arr.pop() so that array reverse can be avoided.Ea
@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.Inoculum
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?Marsupial
Currently in Chrome 53 and Firefox 48 it's one of the slowest approach - check on perfjs.info/array-iterationNiemann
@Alireza agree, I have a comment for that in my answer also.Inoculum
C
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;
}
Chrysanthemum answered 22/5, 2017 at 9:28 Comment(4)
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.Versieversification
Here is a jsperf of what I am talking about: jsperf.com/javascript-loop-testing-let-vs-varVersieversification
This is only an issue in Chrome. In other Browsers var and let have the same performance - https://mcmap.net/q/36393/-is-there-a-performance-difference-between-39-let-39-and-39-var-39-in-javascriptChrysanthemum
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.Versieversification
W
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
Watermelon answered 24/3, 2022 at 18:3 Comment(2)
Your code is incorrect for pop. arrClone is empty when you try to iterate itRiess
I made an updated version over here: gist.github.com/episage/076ded007d0583f6a275f93a8c9c8047 . for ++ wins for large arrays.Riess
P
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.

Ploughshare answered 18/3, 2011 at 8:9 Comment(0)
E
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

Elizaelizabet answered 24/7, 2014 at 16:21 Comment(2)
Currently in Chrome 53 it's true, but Firefox 48 has the same speed - check on perfjs.info/array-iterationNiemann
thunderguy.com/semicolon/2002/08/13/… says ++i is faster...Maisel
A
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?

Averment answered 18/9, 2017 at 14:3 Comment(1)
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.Leader
M
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

Maddi answered 25/11, 2019 at 4:4 Comment(0)
T
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

Tynishatynwald answered 6/10, 2020 at 5:18 Comment(0)
R
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

Ramification answered 28/10, 2021 at 10:44 Comment(0)
R
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.

Riess answered 4/12, 2022 at 10:40 Comment(2)
Interesting answer, think its nice and up to date and simple. Would be cool if you could show an example of each type.Assam
@GreggoryWiley You can see each type example in the gist link (scroll up)Riess
P
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/

Pedicle answered 8/11, 2014 at 0:10 Comment(0)
F
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?

Flirtatious answered 20/11, 2014 at 14:32 Comment(1)
If you do while (i--) then the truthfulness of i will be tested before decrementing rather than decrementing and then testing truthfulness.Newby
M
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

Meal answered 8/11, 2017 at 17:52 Comment(0)
U
-2

The most elegant solution I know of is using map.

var arr = [1,2,3];
arr.map(function(input){console.log(input);});
Upanddown answered 4/1, 2013 at 22:28 Comment(2)
The question is not asking for the slowest way to iterate through a loopHydrotherapeutics
can speed it up even more with [1,2,3].map(console.log)Jackinthepulpit
S
-2

Try this:

var myarray =[],
i = myarray.lenght;
while(i--){
// do somthing
}
Sweetmeat answered 18/7, 2018 at 2:45 Comment(0)
S
-4

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]) 
   }
}
Sumrall answered 5/10, 2022 at 6:59 Comment(7)
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.Theone
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.Sumrall
"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?Sumrall
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.Sumrall
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 method. With that said, you really should avoid creating sparse arrays in the first place.Theone
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.Theone
But not matter the situation, using the for .. in construct to iterate over an array is plain wrong.Theone

© 2022 - 2024 — McMap. All rights reserved.