3

In javascript, if i want to loop through every element in an array, i have several methods to do that:

1.

for(var i =0; i<array.length; i++){}

2.

array.forEach(function(item, index){});

3.

for (var index in array){}

The first one is the common one, but if i feel lazy, i want to use the second or third one.

But i wonder if there's any difference between them, and in what situation should i choose which?

kikkpunk
  • 1,287
  • 5
  • 22
  • 34

5 Answers5

5

They are all subtly different approaches.

for(var i = 0; i<array.length; i++){} is the tried-and-true method; feels like C, works like C.

  • Iterates over every array index, even those without a corresponding property/item.
  • Works on any object supporting .length and properties with names [0..length); while it also works on sparsely-populated arrays an additional guard may be required.
  • Unlike forEach, this allows the use of continue/break/return as well as manual adjustment of the index from within the loop body, if such is ever required.

array.forEach(function(item, index){}) is the approach I prefer because it is often sufficient, feels cleaner, and is "lazy".

  • Iterates over every array value/index that has an property.
  • Implicitly implies a new function-scope each loop.
  • While defined on Array.prototype it it can be used generally over array-like objects with call/apply.
  • It has more overhead than for..i++ (link stolen from James G.'s comment). However, this often doesn't matter and the relative performance difference will decrease as the work done in the body increases.

for (var index in array){} should not be used when dealing with Array/sequence iteration.

  • Iterates over all not-excluded-from-enumeration properties, traversing [prototype] as well
  • Property names are iterated in an implementation-defined order2

Here is a demonstration of some differences:

var array = [];
array[0] = 1;
array[2] = 2;  // Note that `1 in array` is false as it was never set
array.hello_world = 3;

var a = 0;
for(var i = 0; i<array.length; i++){
    a += array[i]
}
// -> NaN; because array[1] was undefined
console.log("index: " + a);

var b = 0;
array.forEach(function (v, i) {
    b += v;
});
// -> 3; because v was never undefined (as array[1] was skipped)
console.log("forEach: " + b);

var c = 0;
for (var p in array) {
    c += array[p];
}
// -> 6; picked up "hello_world" but didn't pick up missing "1" property
console.log("for..in: " + c); 

2 An example producing different iteration order between browsers:

var a = [];
for (var i = 100000; i > 0; i -= 1000) { a[i] = i; }

var s = "";
for (var p in a) { s += p + ",";  }
console.log(s);

Chrome and IE 10 iterate in ascending numerically; FF iterates in order inserted (for smaller ranges of values FireFox also sorts ascending numerically). Just don't use this approach for iterating a sequence and there won't be any problems like this.

Community
  • 1
  • 1
user2864740
  • 60,010
  • 15
  • 145
  • 220
1

The third is a bad idea, because it iterates over an objects properties, not over the items in an array (although you can mistake it for that, since the items are properties (but there can be other properties, too)).

Here's a relevant other SO question: Loop through an array in JavaScript

And a useful off-site discussion: http://javascriptweblog.wordpress.com/2011/01/04/exploring-javascript-for-in-loops/

And from the Crockford: http://javascript.crockford.com/code.html#for%20statement

Community
  • 1
  • 1
0

Use 1 when you have loop, not iterator. Second option is most common when you want to iterate through array. This one should not be used to iterate over array, that's why:

x = []
> []
x.a = 1;
> 1
x[0] = 2
> 2
for (var i in x) console.log(i);
> 0
> a
Anatoliy
  • 29,485
  • 5
  • 46
  • 45
0
  1. Will only work for arrays. You can't traverse objects this way.
  2. Will only work for arrays. Slower than #1, but by creating a new function scope you ensure that any asynchronous callbacks containing your index or item parameters are capturing the current value as they pass through the scope rather than their final value.
  3. Works great for walking over objects as well as arrays. Slightly slower than #1 when dealing with arrays. This can be dangerous because some naughty libraries like PrototypeJS add properties to the Array prototype, which means you'll end up with indexes that don't actually represent items in the array. Don't use this if there is any chance of your code being used on the same page as a library that does this.

Another interesting difference arises if you have "undefined" values in your array. In my experience, this is uncommon, but it would make a difference. For example:

var array = [0, undefined, 2, 3];
array[2] = undefined;
delete array[3];
array[5] = 5;

Approach #1 hits indexes 0, 1, 2, 3, 4, 5, showing undefined values at 1, 2, 3, and 4.
Approaches #2 and #3 hit indexes 0, 1, 2, 5, showing undefined values at 1 and 2.

StriplingWarrior
  • 151,543
  • 27
  • 246
  • 315
0

The first one is ok, since the collections in javascript are indexable, and, the third one to loop between all elements without reference.

If the order does not matter, you could try to improve the performance with this:

var i = list.length;
while (i--)
{
   var item = list[i];
   // manipulate item           
}
Felipe Oriani
  • 37,948
  • 19
  • 131
  • 194