I was surprised when I was able to reproduce a bug with a minimum amount of code. Note that in this minimalist example Array.indexOf isn't being called. Also note that I've tried several different implementations of indexOf, including several from stackoverflow.com.
The bug is, when the for...in executes in IE, three alerts are displayed: "indexOf", "0", and "1". In FF, as one would expect, only two ("0", "1") appear.
<html>
<body onLoad="test();">
<script language="javascript">
var testArray = ['Foo', 'Bar'];
if(!Array.prototype.indexOf) {
Array.prototype.indexOf = function (obj, fromIndex) {
if (fromIndex == null) {
fromIndex = 0;
} else if (fromIndex < 0) {
fromIndex = Math.max(0, this.length + fromIndex);
}
for (var i = fromIndex, j = this.length; i < j; i++) {
if (this[i] === obj)
return i;
}
return -1;
};
}
function test() {
var i;
for(i in testArray) {
alert(i);
}
}
</script>
</body>
</html>
Can anyone explain this? I've already changed my code to use a while
so I'm not under the gun, but this one really has me stumped. It reminds me of memory overrun errors in c.
See "for in Intrigue" on the Yahoo! User Interface blog.
The reason your code is working as expected in Firefox is because you haven't added your own
indexOf
method in Firefox. Thefor in
loop iterates over all the keys in the object's prototype chain, including theindexOf
method you added. Douglas Crockford suggests the following solution:Alternatively, you can just filter out functions:
Also, as "nickf" points out, it is best not to use the
for in
loop for iterating over arrays. Thefor in
loop is intended for iterating over the keys in an object.Steve
for .. in
is meant for looping through object properties, definitely not arrays.Stick to the standard:
More info at the Mozilla Developer Centre: