Take the 2-minute tour ×
Programmers Stack Exchange is a question and answer site for professional programmers interested in conceptual questions about software development. It's 100% free, no registration required.

I'm looking for a definitive answer to why extending built-in prototypes is so heavily chastised in the JS developer community. I've been using the Prototype JS framework for a while, and to me doing [1,2,3].each(doStuff) seems much more elegant than $.each([1,2,3], doStuff). I know that it creates "namespace pollution," but I stil don't understand why it's considered to be a bad thing. Also is there any real performance degradation associated with extending built-in prototypes? Thanks!

share|improve this question

migrated from stackoverflow.com Aug 29 '11 at 6:44

This question came from our site for professional and enthusiast programmers.

1  
One thing is that for(var ... in ...) loops get messed up since prototype functions are passed too. –  pimvdb May 16 '11 at 21:07
3  
"heavily chastised", really?! good god, man :] are you ok? –  pixelbobby May 16 '11 at 21:10

5 Answers 5

I suggest you to read this article which I think explains pretty well why extending objects is a bad idea, with regard to Prototype also.

In summary:

Lack of specification

Exposure of "prototype objects" is not part of any specification. [...] In order for implementation to conform to DOM Level 2 fully, there's no need to expose those global Node, Element, HTMLElement, etc. objects.

Host objects have no rules

DOM objects are host objects [...] Host objects may implement these internal methods with any implementation-dependent behaviour, or it may be that a host object implements only some internal methods and not others.

[...] Internal methods behavior is implementation-dependent. [...] By definition, you are working with something that's allowed to behave in unpredictable and completely erratic way.

Chance of collisions

Given huge amount of environments in use today, it becomes impossible to tell if certain property is not already part of some DOM. [...]

Every named form control shadows properties inherited through prototype chain. The chance of collisions and unexpected errors on form elements is even higher.

Employing some kind of prefixing strategy can alleviate the problem. But will probably also bring extra noise.

Performance overhead

[...] browsers that don’t support element extensions—like IE 6, 7, Safari 2.x, etc.—require manual object extension. The problem is that manual extension is slow, inconvenient and doesn’t scale.

[...] once you start extending elements, library API most likely needs to return extended elements everywhere. As a result, querying methods like $$ could end up extending every single element in a query.

IE DOM is a mess

As shown in previous section, manual DOM extension is a mess. But manual DOM extension in IE is even worse [...]

Bonus: browser bugs

share|improve this answer

Another reason is code readability/maintainability. If another developer (especially a newbie) is reading my code and sees [0, 1, 2].foo(...), they may not know what the foo method is or where to find documentation/source for it. Is foo is an extension to the language added by prototype.js, or by another library in use, or by some other portion of my code in another file, or is it a native JavaScript method that they didn't know about? They need to hunt for it and may not find it right away (or if there are conflicts they may not find the right one).

With the jQuery approach, if you see $.foo(...), the namespace of the foo method makes it obvious where to find its definition/documentation if you don't know what it does.

share|improve this answer

Here's the basic issue: What happens if you have two tools that extend prototypes in incompatible ways, or which extend commonly-called methods in ways such that they yield different results (this is a particular issue for for...in in JavaScript), thus causing code that relies on their normal behavior to break?

Basically, it's the same issues that you have when you mis-use global variables. By itself, perhaps nothing bad happens. But, it opens you up for trouble when two ostensibly-separate pieces of code suddenly step on each other (and it's a pain to debug when that happens).

Certainly prototype.js is pretty well-known and most tools work around what it does. Similarly, I'm sure there are cases where extending base prototypes is the right thing to do. But, it's something to approach with caution.

share|improve this answer

Not sure if this is really still an issue anymore, but my experience with earlier versions of Internet Explorer is that sometimes it wasn't even possible to extend certain build-in types.

share|improve this answer

There are two separate issues here. The first is the general extending of built-in prototypes, and the other is specifically extending DOM prototypes. The arguments against extending built-in prototypes:

  • Potential clashes: two pieces of code from different sources both defining the same property on the same prototype
  • Side-effects: extending Array.prototype or Object.prototype can have knock-on effects, such as adding the extension methods being enumerated in a for...in loop

As for extending DOM prototypes, the potential clash argument above still applies. Additionally, DOM nodes are host objects and as such are not subject to any of the normal rules of native JavaScript objects. They can essentially do what they like and are under no obligation to provide sensible prototype objects or even allow extra ("expando") properties. IE in particular exercises this right, providing no prototypes for DOM objects before IE 9 and having various weirdnesses about properties on various DOM objects (although you're generally OK assigning properties to elements, provided nothing's set document.expando to false.)

share|improve this answer

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.