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
indexOfmethod in Firefox. Thefor inloop iterates over all the keys in the object’s prototype chain, including theindexOfmethod 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 inloop for iterating over arrays. Thefor inloop is intended for iterating over the keys in an object.Steve