Tuesday, August 14, 2007

Don't use the Javascript for...in loop for arrays!

Like most web developers, I use several languages, and sometimes I get them mixed up. I recently took a deep dive into Ruby, and during the summer I took a break from code work. Getting back to it now, I started on a project involving some simple Javascript, and I ran across some source code containing a for construct that looped much like php's foreach or Ruby's object.each. I welcomed a break from writing tedious for loops with counters and tried to use the construct to iterate over an array. It went great! I.e.

abc = [1, 2, 3];
for (letter in abc) {
alert(letter);
}

However, when I grabbed a collection of elements using Prototype's document.getElementsByClassName() function, and tried to iterate over it using the same technique, I ran into big problems. It turns out:
A for...in loop iterates over the properties of an object in an arbitrary order. [...] Although it may be tempting to use this as a way to iterate over an Array, this is a bad idea. The for...in statement iterates over user-defined properties in addition to the array elements, so if you modify the array's non-integer or non-positive properties (e.g. by adding a "foo" property to it or even by adding a method or property to Array.prototype), the for...in statement will return the name of your user-defined properties in addition to the numeric indexes. Also, because order of iteration is arbitrary, iterating over an array may not visit elements in numeric order. Thus it is better to use a traditional for loop with a numeric index when iterating over arrays.

(Source: MozDev JS reference)

Lesson learned: RTFM.

Edit: it's amazing how easy you can find information, once you know what you're looking for. Here's a blog post that explains the problem and its reasons clearly.