My JavaScript book is out! Don't miss the opportunity to upgrade your beginner or average dev skills.

Thursday, July 26, 2007

Quick Fix - Internet Explorer and toString problems

As You can read on precedent post I'm testing common libraries extend behaviour, both for objects or constructors.

One feature that many developers seems to ignore is IE behaviour when an object contains an explicit toString method.

Look at this simple example:

for(var key in {toString:function(){return "bye bye IE"}})
alert(key);

now test them with IE 5, 5.5, 6 or last 7 version.

What's up? ... absolutely nothing ... so what the hell?

IE doesn't recognize that toString method as explicit one but it "thinks" that's a native one.

This means that a lot of extend functions doesn't assign correctly this method if client broser is IE so every extended object will simply have native or prototyped toString method and not new explicit one.

How to fix this IE behaviour ?

// generic object/instance
var o = {
a:"a",
b:"b",
toString:function(){
return "hello IE too"
}
};

for(var key in o){
// doSttuff ... for example
alert(key);
};
/*@cc_on if(o.toString!=={}.toString){
// doStuff ... for example
alert(o.toString);
}@*/

Since only IE has this problem a conditional comment should be a good solution but this is not required, every other browser will simply check/assign one more time toString method if present.

You can use Object.prototype.toString instead of {}.toString but I think performances are not a problem in both cases.

What are libraries that don't care about this IE problem?

It seems that jQuery, MooTools and probably other libraries don't care about this IE problem while dojo, for example, does more than one check:

if(dojo.isIE &&
(typeof(props["toString"]) == "function") &&
(props["toString"] != obj["toString"]) &&
(props["toString"] != tobj["toString"])
)
obj.toString = props.toString;


Dean Edwards checked valueOf prototype too, so the complete fix should be this one:

/*@cc_on
if(o.toString!==Object.prototype.toString){
// doStuff
}
if(o.valueOf!==Object.prototype.valueOf){
// doStuff
}
@*/

2 comments:

Stijn said...

Thanks! This was the fix i needed. It turn out Prototype also doesn't account for this.

Stijn said...

Correction. It was broken in prototype 1.6.0-rc1 and is now fixed in prototype 1.6.0.