Extending Host Objects: Evil; Extending Native Objects: Not Evil But Risky

Kangax has a good article on extending JavaScript native objects and host objects. He begins by clarifying that extending host objects (e.g. Element) is truly evil. Host objects do not have strong specs and have no rules and extending them risks collisions. Kangax has an older post talking about extending objects. There he says that Prototype JS's biggest mistake was extending Element. I find that particularly interesting since Kangax was an influential voice in the Prototype JS community.

I completely agree; problems with Element was one of the top reasons I stopped using Prototype JS. When Chrome 1.0 came out, for example, it was apparent that extending Element was far from future proof, because, for one, Chrome 1.0 sometimes created elements that didn't inherit from Element.

So back to my first point: the difference between native objects and host objects. Extending native objects such as Array is not necessarily evil. Shimming methods on native objects is OK if you carefully follow spec. But that means adding your own methods to Array.prototype is bad. Prototype JS's Array.prototype.map function is a great example: it was created before the spec for Array.prototype.map was created. Now that Array.prototype.map has been implemented in most browsers, Prototype JS is overriding the proper version with its own version. That is damaging.

But yes, shims are OK. Technically. It is OK to define JSON or Array.prototype.indexOf for browsers that lack them as long as you follow spec. Just remember that following spec is hard. It is so hard in fact, that you probably shouldn't use shims.

It's best in principal and practice to avoid extending objects you don't own. In the special case of using shims, extending native objects is OK as long as you use well-researched, well-tested shims. In practice it's very hard to find good implementations, so it is safest to avoid extending object natives altogether.

I recommend just staying away from altering prototypes of all objects you don't own and leave it at that.