There are actually all kinds of ways to iterate through an array in JavaScript. Here, I will concentrate on six of them, describe their advantages, and do performance testing to actually prove which of them is the faster.
Loop 1 – the native for loop
for (var i=0; i < arrTestData.length; i++) { /* do stuff */ };
We’ve all seen this a million times. It is the easiest to read, and the most common. It is also the least efficient.
Loop 2 – the native for loop improved
for (var i=0,j=arrTestData.length; i<j; i++) { /* do stuff */ };
The improvement here, is that a second variable j
is employed, to stop us having to query the length property of the array with every iteration. Getting the length can be a costly process and it makes more sense to just do this once. Where it is important that iterate incrementally, and in ascending order (i.e. 0,1,2,3,4,5) this is the fastest method.
Loop 3 – the native for loop in reverse
for (var i = arrTestData.length - 1; i >= 0; i--){ /* do stuff */ };
The main advantage of this method is that only one variable is employed. It is slightly faster than the other for loops, but goes in descending order (i.e. 5,4,3,2,1,0) which may make it inappropriate for your needs.
Loop 4 – the native while loop
var i = 0; while (i < arrTestData.length) { /* do stuff */ i++; };
This is essentially the same as Loop 1. We are still querying the length of the array with every iteration.
Loop 5 – the native while loop in reverse
var i = arrTestData.length - 1; while (i > 0) { /* do stuff */ i--; }
This is essentially the same as Loop 2. We are storing the length of the array, to avoid querying with every iteration.
Loop 6 – the native while loop in reverse improved
var i=arrTestData.length; while (i--) { /* do stuff */ }
This is the tidiest code, and the fastest. Since a zero integeric value is falsy, our condition is as simple as it could be, and only one variable is employed. I give credit to Richard Hubbard (get a blog already, Richard!) for showing me this.
Below, are the results of my testing.
OS | Browser | Test | Result 1 | Result 2 | Result 3 | Average |
---|---|---|---|---|---|---|
OSX 10.5.6 | Firefox 3.0.5 | Loop 1 | 46ms | 47ms | 46ms | 46ms |
Loop 2 | 31ms | 32ms | 31ms | 31ms | ||
Loop 3 | 34ms | 33ms | 33ms | 33ms | ||
Loop 4 | 46ms | 45ms | 46ms | 45ms | ||
Loop 5 | 32ms | 32ms | 32ms | 32ms | ||
Loop 6 | 29ms | 29ms | 29ms | 29ms | ||
OSX 10.5.6 | Safari 3.2.1 | Loop 1 | 44ms | 45ms | 43ms | 44ms |
Loop 2 | 33ms | 32ms | 34ms | 33ms | ||
Loop 3 | 31ms | 33ms | 31ms | 31ms | ||
Loop 4 | 45ms | 45ms | 45ms | 45ms | ||
Loop 5 | 33ms | 33ms | 33ms | 33ms | ||
Loop 6 | 29ms | 29ms | 29ms | 29ms | ||
OSX 10.5.6 | Camino 1.6.4 | Loop 1 | 106ms | 93ms | 91ms | 96ms |
Loop 2 | 67ms | 64ms | 61ms | 64ms | ||
Loop 3 | 61ms | 64ms | 61ms | 62ms | ||
Loop 4 | 91ms | 90ms | 90ms | 90ms | ||
Loop 5 | 61ms | 64ms | 67ms | 64ms | ||
Loop 6 | 60ms | 60ms | 60ms | 60ms | ||
OSX 10.5.6 | Opera 9.61 | Loop 1 | 34ms | 32ms | 31ms | 32ms |
Loop 2 | 23ms | 24ms | 29ms | 25ms | ||
Loop 3 | 24ms | 23ms | 23ms | 23ms | ||
Loop 4 | 32ms | 31ms | 32ms | 31ms | ||
Loop 5 | 22ms | 26ms | 23ms | 23ms | ||
Loop 6 | 26ms | 25ms | 25ms | 25ms | ||
Windows XP SP2 | Chrome 1.0.154.36 | Loop 1 | 2ms | 3ms | 2ms | 2ms |
Loop 2 | 2ms | 2ms | 2ms | 2ms | ||
Loop 3 | 2ms | 2ms | 2ms | 2ms | ||
Loop 4 | 3ms | 3ms | 3ms | 3ms | ||
Loop 5 | 2ms | 2ms | 2ms | 2ms | ||
Loop 6 | 2ms | 2ms | 2ms | 2ms | ||
Windows XP SP2 | IE 7.0.5730.13 | Loop 1 | 171ms | 172ms | 172ms | 171ms |
Loop 2 | 125ms | 125ms | 125ms | 125ms | ||
Loop 3 | 125ms | 125ms | 125ms | 125ms | ||
Loop 4 | 1172*ms | 172ms | 172ms | 172ms | ||
Loop 5 | 125ms | 125ms | 141ms | 130ms | ||
Loop 6 | 125ms | 125ms | 125ms | 125ms | ||
Windows XP SP2 | FF 3.0.5 | Loop 1 | 37ms | 37ms | 37ms | 37ms |
Loop 2 | 26ms | 26ms | 26ms | 26ms | ||
Loop 3 | 25ms | 26ms | 25ms | 25ms | ||
Loop 4 | 37ms | 36ms | 37ms | 36ms | ||
Loop 5 | 25ms | 25ms | 25ms | 25ms | ||
Loop 6 | 27ms | 26ms | 27ms | 26ms | ||
Windows XP SP2 | Safari 3.2.1 | Loop 1 | 53ms | 52ms | 53ms | 52ms |
Loop 2 | 40ms | 39ms | 40ms | 39ms | ||
Loop 3 | 39ms | 40ms | 40ms | 39ms | ||
Loop 4 | 55ms | 55ms | 54ms | 54ms | ||
Loop 5 | 41ms | 41ms | 40ms | 40ms | ||
Loop 6 | 37ms | 37ms | 37ms | 37ms | ||
Windows XP SP2 | IE 6 (multiple IEs) | Loop 1 | 156ms | 172ms | 156ms | 161ms |
Loop 2 | 109ms | 125ms | 109ms | 114ms | ||
Loop 3 | 110ms | 125ms | 125ms | 120ms | ||
Loop 4 | 156ms | 1313*ms | 156ms | 541ms | ||
Loop 5 | 125ms | 109ms | 125ms | 119ms | ||
Loop 6 | 125ms | 110ms | 125ms | 120ms | ||
Windows XP SP2 | Opera 9.63 | Loop 1 | 16ms | 31ms | 16ms | 21ms |
Loop 2 | 16ms | 15ms | 16ms | 15ms | ||
Loop 3 | 15ms | 16ms | 16ms | 15ms | ||
Loop 4 | 31ms | 16ms | 31ms | 26ms | ||
Loop 5 | 15ms | 16ms | 16ms | 15ms | ||
Loop 6 | 0ms | 15ms | 16ms | 10ms |
I did every test three times, and took the average as the result. Internet Explorer 6 and 7 both presented a confirm dialogue box, asking if I wanted to keep running the script, which paused execution of the code. This resulted in two vastly bloated results, which I have generously ignored. It didn’t help – IE is the obvious loser here in every instance, surprisingly showing very little improvement between IE6 and IE7.
Copying the data was a pain – although in OSX I could copy and paste from pretty much any source, including alert dialogue boxes. In Windows only Firefox would let me do this.
A shock in all of this, was just how fast Chrome performed, clocking in at 100,000 iterations per millisecond! I actually wrote different versions of the code just for Chrome, just to ensure it was actually doing something. That V8 engine they have in there is amazing.
The point of this, though, is not to compare browser speed. Of course, we can’t compare between OSX and Windows XP in this instance, the hardware was different. Also, this is just a very specific and small set of tests and cannot be considered a fair test of browser speed. Really, what we wanted to achieve was to see which method of iterating through an array is the most efficient.
To that end, here is a final table, showing the average result across browsers for each loop.
Test | Average Result (ms) |
---|---|
Loop 1 | 73.6 |
Loop 2 | 52.6 |
Loop 3 | 52.7 |
Loop 4 | 73.1 |
Loop 5 | 53.6 |
Loop 6 | 51.4 |
The obvious conclusion is that although Loop 6 is the fastest, there is not that much in it – whereas Loop 1 and Loop 4 are dramatically slower than the others, demonstrating just how expensive the querying of the length property is.