January 2011
7 posts
@matasar and I discovered a really neat “feature” of Internet Explorer: if you enumerate an object using a for…in loop, IE will ignore any property named toString. This bit us because we were using such a loop to add methods to an object’s prototype using code like this:
var someNewMethods = {
someOtherMethod: function() {
…
},
toString: function() { // overrride native toString
return 'I am a foo.';
}
}
for (var p in someNewMethods) {
ExistingObjectType.prototype[p] = someNewMethods[p];
}
In sane browsers like Firefox, Safari and Chrome, this will add someOtherMethod and override the toString method of the ExistingObjectType’s prototype. In IE, toString is ignored in the loop, so it’s left unmodified. (And the native toString method for any object is always the ever-helpful string "[Object object]".)
It turns out this is a known bug in IE. Essentially, for…in loops ignore any properties that would otherwise be inherited from the Object type, including toString, valueOf and others.
The solution, sadly, appears either to be to avoid ever using properties with those names (at least if you expect to need to enumerate them), or to treat them as a special-case, with some code like this:
var thoseOtherProps = [
'constructor',
'toString',
'valueOf',
'toLocaleString',
'isPrototypeOf',
'propertyIsEnumerable',
'hasOwnProperty'
];
thoseOtherProps.forEach(function(p) {
if (someNewMethods.hasOwnProperty(p)) {
ExistingObjectType.prototype[p] = someNewMethods[p];
}
});
Blech. (And of course, IE also doesn’t support forEach natively, so this code assumes that you’ve added such a method to the Array prototype.)