0

I have an array var test = [1, 2, 3]. When using for in method to go through the array something wrong happened. Please see the snippet here:

var test = [1, 2, 3]    
for (var i in test) {
    alert(i);
}

It will alert "0", "1" and "2" here in the snippet. But in my computer, it will alert "0", "1", "2" and an "equal". I think equal is a method of the array object itself.

This behavior didn't appear a week ago, thus my previous code which was written using for in is strongly affected.

Can anyone suggest what causes this strange behavior? And how may I avoid this behavior without changing my code?

Vilx-
  • 104,512
  • 87
  • 279
  • 422
Summer Sun
  • 947
  • 13
  • 33

2 Answers2

2

This is because some library you're using (or maybe even something you wrote yourself) does this:

Array.prototype.equals = function() { ... }

This is the downside of the in operator - it enumerates the extra properties too. You can use the hasOwnProperty() method to check i and ignore the properties that are not set on the object. Or, for arrays, use this instead:

for (var i = 0; i < test.length; i++ )

Of course, this only works on continuous arrays that start at 0.

Vilx-
  • 104,512
  • 87
  • 279
  • 422
2

for (var i in test) enumerates all properties of the test array (remember an Array is an Object and can have arbitrary non-numeric properties too). This includes not only the indexes of the array, but also any enumerable properties that someone else might have added to the Array object. This is generally considered the wrong way to enumerate an array. This structure is made to enumerate all properties of an object, not only the array indexes of an array.

Instead, you can use any of these:

for (var i = 0; i < test.length; i++) 
test.forEach(fn);
test.every(fn);
test.some(fn);

These will only enumerate actual array items, not other properties added to the array.

On sparse arrays (where not all items have been initialized), the for loop will visit every item (even the uninitialized items), whereas the others will skip the uninitialized items.


The fact that you are seeing the equal property show up in your enumeration means that someone has added an enumerable property to the Array object and thus it shows up with the for (var i in test) form of enumeration.


In ES6, you can also use the of iteration technique and this will be safe from the non-array element properties and will return the same items that .forEach() will return. Note, it also differs from in because it delivers the actual array values, not the array indexes:

var test = [4, 7, 13];
test.whatever = "foo";
for (var item of test) {
    console.log(item);   // 4, 7, 13
}
jfriend00
  • 683,504
  • 96
  • 985
  • 979