When not to use the for...in statement

So today a colleague of mine ran into a small JavaScript problem. One of his functions ran an Ajax request which returns a JSON object which is parsed using jQuery’s parseJSON method. The resulting array is then ran through another function which does some calculations and displays the results in a list.

Here’s where the problem starts. The method that does the calculations runs through the array using the native JavaScript for...in loop, in which a calculation method is applied to every item in the array. However, for some reason, the list contained one extra item with the value NaN. Upon inspecting the array, I found that there was an extra item called map, which was a function. You can probably already guess by now why the calculation didn’t work as it was expected to, and rightly so, especially when the value used in the calculation was a function.

To simplify things, take the below code snippet as an example;

var arrayObj = new Array();

arrayObj[0] = 1;
arrayObj[1] = 2;
arrayObj["myfunction"] = function(){ alert('This is my function') };

for(var i in arrayObj){
    document.write(arrayObj[i]) * 5 + "<br />";
}

This will actually result in JavaScript rendering the below;

5
10
NaN

So where’s the problem? Well, firstly the for…in statement is a loop method to be used when iterating through object properties. So to use it for iterating through an array is abuse in itself, and if it produces unexpected results, well, that’s to be expected.

Now take this example;

var arrayObj = new Array();

arrayObj[0] = 1;
arrayObj[1] = 2;
arrayObj["myfunction"] = function(){ alert('This is my function') };
arrayObj[10] = 10;

for(var i in arrayObj){
    document.write(arrayObj[i]) * 5 + "<br />";
}

This piece of code will actually produce;

5
10
NaN
50

However, when you check the array length, you’d notice that it shows up as 11. The for-in statement completely ignores the undefined items in the array, unlike the for loop. Iterating through the above array using the for loop will result in the below;

5
10
NaN
NaN
NaN
NaN
NaN
NaN
NaN
50

So as a general rule of thumb, one should always use the for loop when iterating through an array, to avoid having problems with non-array items. The below example will do what we actually want done;

var arrayObj = new Array();

arrayObj[0] = 1;
arrayObj[1] = 2;
arrayObj["myfunction"] = function(){ alert('This is my function') };

for(var j = 0; j < arrayObj.length; j++){
    document.write(arrayObj[j]) * 5 + "<br />";
}

I hope this helps clear some stuff up.

Wassalam

UPDATE:

A friend of mine pointed out to me that if I were to use the for...in statement, it is important to also use the .hasOwnProperty() method to make sure the object we’re testing are our object properties and not the prototype chain. This is important since you only want to iterate through your own object properties and not the prototype chain, and without using the .hasOwnProperty() method, the for...in statement will iterate through the prototype chain. Definitely not what we want.


© 2017. All rights reserved.

Powered by Hydejack v7.5.0