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.