I’ve been using Prototype + Scriptaculous for my current project. It surprises me that I haven’t encountered this problem until just now though.

I noticed some funky behavior today when I tried iterating over an array of values. I have loved Prototype for some time. It’s elegant style, ease of DOM manipulation, and ummm.. it’s style!

However, the behavior I just encountered I don’t care for. I know that Prototype modifies (extends) the builtin objects of Javascript, namely Array and Object. I like the added bang for the buck that I get. But look at this test:

var l_a = ["A","B","C"];
var l_r = "";
for(var l_x in l_a){l_r += l_x + " ";}
alert((l_r == "0 1 2 ") + "\n" + l_r);

What do you think that prints out? Chances are you’re wrong. It actually prints out the array… followed by all the functions used to extend the Array object.

false
0 1 2 each eachSlice all any collect detect findAll grep include inGroupsOf inject invoke max min partition pluck reject sortBy toArray zip size inspect find select member entries _reverse _each clear first last compact flatten without reduce uniq clone toJSON call

The same sort of problem happens if you were to use object literals instead of arrays. Let me show you the bad and good ways to use each of them.

Array looping, BAD

var l_a = ["A","B","C"];
var l_r = "";
for(var l_x in l_a){l_r += l_x + " ";}
alert((l_r == "A B C ") + "\n" + l_r);
 
Output:
false
A B C each eachSlice all any collect detect findAll grep include inGroupsOf inject invoke max min partition pluck reject sortBy toArray zip size inspect find select member entries _reverse _each clear first last compact flatten without reduce uniq clone toJSON call

Array looping, GOOD

var l_a = ["A","B","C"];
var l_r = "";
for(var l_x = 0;l_x < l_a.length;l_x++){l_r += l_a[l_x] + " ";}
alert((l_r == "A B C ") + "\n" + l_r);
 
Output:
true
A B C

Object looping, BAD

var l_a = {};
l_a["a"] = "A";
l_a["b"] = "B";
l_a["c"] = "C";
var l_i;
var l_r = "";
for(var l_x = 0;l_x < l_a.length;l_x++){l_r += l_a[l_x] + " ";}
alert((l_r == "A B C ") + "\n" + l_r);
 
Output:
false

Object looping, GOOD

var l_a = {};
l_a["a"] = "A";
l_a["b"] = "B";
l_a["c"] = "C";
var l_i;
var l_r = "";
for(var l_x in l_a){l_r += l_x + " ";}
alert((l_r == "a b c ") + "\n" + l_r);
 
Output:
true
a b c

Long story short…

When using arrays always iterate over the elements with:

for(var l_x = 0;l_x < l_a.length;l_x++){}

When using object literals always iterate over the elements with:

for(var l_x in l_a){}