Hacker Newsnew | past | comments | ask | show | jobs | submitlogin
JavaScript Prototypes Made Easy (javascriptweblog.wordpress.com)
131 points by toffeescript on June 30, 2012 | hide | past | favorite | 33 comments


Unfortunately, there's no real way to make JS prototypes easy, simply because it's a poorly-designed system with way too many "wait, what?" moments.

If you want classical inheritance, there are many tiny JS libraries that will give it to you. If you want classical prototypes, there are also JS libraries that will give that to you. Or you can write your own.

But trying to make JS behave as either one by hand will just waste your time and frustrate you.

(note: this is a good article for explaining the underlying system behind JS prototypes, I just don't recommend that you interact with said system unless you have to)


I agree that's a good article. I would have loved to read it 12, 10 or 8 years ago.

Coming from a design background, JavaScript was my first programming language at the end of the century. I simply learned programming through JavaScript's prototypal nature. I've used it extensively for many years before my first experience with a more classical language (AS3…). JS prototypes seem very natural to me. After a few years of AS3 (and a very short bit of C#), I'm not sure at all that the "classical" way is fundamentally better than JS's way.

Newcomers to JavaScript should drop their "classical" baggage before they embark. I'm starting to learn Python (2 week ends, now) and I'm not going to bring my AS3isms and my JSisms with me. Is that too hard to learn a new language with an open mind?


I don't think that's the issue, though I did come to JS from a python background, so that that for what it's worth.

For me the problem is that people tend to use prototypal inheritance to implement class inheritance patterns, but there are so many ways to do that, so whenever you read code, it takes a while to figure out what people are doing.

If there was a large gain to prototypal inheritance, I might be willing to accept it, but I havent' seen (does anyone have examples?) of really cool/useful things you can do with prototypes that you cannot do with class based inheritance? Because the increased flexibility leads to confusion without added benefit, I don't see the point.

Contrast that with dynamic typing, where I think there are huge benefits which offset the added cost.

also - from reading that article, it seems that JS's prototypal system has a large number of gotchas, and thats bad regardless of what kind of inheritance system your language implements.


I don't have examples of prototype inheritance being better than classical inheritance because there is no classical inheritance in JavaScript. In JS, prototypal inheritance is the de facto way to do inheritance. Whether you like it or not.

Now what is the most productive/sane path?

1. work against the language to have something that looks like classical inheritance.

2. work with the language and learn prototypal inheritance


What I mean is that projects like coffeescript, and spine.js build classical inheritance patterns on top of JS and they work rather well.

I'm looking for someone to contrast either a classical inheritance system built on top of JS prototypes vs using JS prototypes in another way, OR just show me something cool you can do in JS prototypes, that you can't do with python or ruby classes. Contrasting js prototypes with classes in another language is fine for this exercise, I'm trying to understand conceptually why prototypal inheritance is good. Otherwise, I don't see how prototypal inheritance adds value over python/ruby inheritance schemes.

I also believe it's completely feasible and logical to critique language features, and still use them at the same time out of necessity. I still use prototypal inheritance, just through coffeescript classes


There are many small and big projects providing approximations of a class system in JS. All of them use prototypal inheritance under the hood.

They work well because, for most of us, both systems are designed and used for the same thing: creating base objects, instanciating objects based on those base objects and creating other base objects based on previous base objects.

All of the pseudo-classical systems devised by library authors are used exactly the same way as we have used prototypal inheritance for years before JavaScript became fashionable again. Both systems do exactly the same thing and using one over the other is just a matter of taste or habit.

I see a lot of people claiming that the classical system is superior to the prototypal system and that JavaScript sucks because it is designed around the wrong system. AFAIK, nobody is claiming the opposite. Prototypal inheritance has been there since the beginning, some people learn it without complaining, some others write long rants because they don't want to adapt to another paradigm. Guess which ones are the most reasonable?

Prototypal inheritance doesn't add value over other inheritance systems. It's just the default system at the heart of JavaScript. Whether it's better or worse doesn't matter as there's no alternative. Comparing JavaScript's prototypal inheritance to Java/PHP/Ruby/Python/C++/C#'s own systems makes no sense because we are not in a position to choose. We can't use any of these languages to dynamize your HTML in a browser, do we?

The day a vendor decides to expose the DOM to Python || Ruby will be an interesting day, for sure. But for now…

… if you don't like prototypal inheritance use one of those classical libs if it makes you feel better because, in reality, it makes no difference: you'll still use prototypal inheritance anyway.

But, to answer your question, I like the fact that I can add Car.prototype.honk on the fly, anywhere in my script, and be certain that all of the objects inheriting from Car (SportsCar, DeliveryCar, CheapCar…) will be able to honk(). I know this is available in Ruby, I don't think it's doable in PHP and I don't know for the other languages.


I also came from a scripting background (Perl) but are you seriously telling real programmers coming to Javascript from C, C++, and the like that they should change their way of thinking to fit a truly broken system originally used mostly by web designers?


Prototypes are not a "truly broken system originally used mostly by web designers". The original idea came from a rather elegant language called Self[1], not designed for web work at all. It really is a good idea fundamentally, and, even if the JavaScript implementation is not great, it's still very useful.

[1]: http://ranger.uta.edu/~nystrom/courses/cse3302-fa10/selfPowe...

Also, people coming from C do not have any preconceptions about OO--C does not provide any OO facilities at all! They would have to change their way of thinking when transiting to any OO or functional language.

C++'s model is also not particularly strong. There is a famous quote from Alan Kay (the initial inventor of OO): "I invented the term Object-Oriented and I can tell you I did not have C++ in mind." I personally have not used C++ much, but there seems to be a consensus that it's too complicated (especially in regards to multiple inheritance) and too error-prone. So I think it's more than reasonable to have people coming from C++ change their way of thinking!

Whenever you switch to a sufficiently different language, you have to change your way of thinking. This is not only natural but also healthy.

Finally, implying that people using JavaScript aren't real programmers is extremely condescending.


It is not broken.

First read Steve Yegge's excellent article on the Universal Design Pattern to understand why prototypes are really useful and natural http://steve-yegge.blogspot.co.uk/2008/10/universal-design-p...

Then try to understand that prototypes are more natural in a dynamic language because they are completely dynamic. Classical inheritance is generally static.

It might help using a language that has less syntactic confusion than Javascript, Lua is the best known, or Self or Io.


Yes.

Different languages, different paradigms, different designs, different flaws…

You are learning a new language, not toying with a broken implementation of your preferred language. JS is not a subset of C++ or Java. Think/act accordingly.

I don't use ".prototype" in AS3 or PHP because it doesn't make sense. I don't use "class" in JS because it doesn't make sense.

Do it for your own sanity.

It's really quite simple but it seems to be hard for a lot of people.


I completely disagree with you. JS' prototypes may have been poorly designed, but once you understand it, there's no reason you shouldn't use it at its full capabilities.

Now, I do have a lot against enforcing OO behavior in js. Aside from the obvious performance overhead, you might be shielding developers from understanding the very language they're writing code on.


Really nice explanation on a subject way too many JavaScript developers are ignorant about. Definitely worth a read if you've any interest in the language.

I agree with the comments that there's nothing inherently wrong with prototypes (they can be tremendously useful and powerful, and make for a refreshing change from the rigidity of classical inheritance in languages like Java), but JavaScript's particular implementation, unfortunately, does a very good job of disguising their utility.


May I just compliment the author on the clever "dots" at the ends of the "J" glyphs on the website logo that stay in place as you scroll.


I got that too, but upon further inspection, it's a rendering bug.


What on earth are you talking about, man?


I see it too, it seems like a CSS bug. The original commenter was probably being sarcastic.


I wasn't ahah. I genuinely thought it was an intentional design element.


great article that clearly articulates js prototypes. I'd have to disagree with ender7 though, I think JS prototypes are not a "poorly-designed system" they're just different from classical forms of OOP inheritance. And contrarily, I would recommend anyone to delve deeper into prototypes - an alternative method to class based OOP.


It still could be much better designed though, compareed to othe rprototipical languages. Prototypes cannot be explicitly accessed or mutated, Object.create wasn't even part of the standard and the whole syntax with function constructors and having to set the prototype property is a very ugly hack.


I haven't used any other prototypical languages so I can't say how js compares... Can you give me the best prototypical language? - I'd like to check it out and see for myself. Still, as far as shimming up a clean cross browser API prototyping is extremely usefull.


I don't know much about this, but I've heard Self mentioned as the prototypical prototypical language many times.

http://en.wikipedia.org/wiki/Self_(programming_language)


It's the language where the idea came from originally. It's basically the Smalltalk of prototype-based OO :).

Here's a nice paper about it: http://ranger.uta.edu/~nystrom/courses/cse3302-fa10/selfPowe...


JavaScript's prototypes really are poorly designed, though. To see how it probably should have been done, check out the programming language Io (http://iolanguage.com/) or Douglas Crockford's note on prototypal inheritance in JavaScript at http://javascript.crockford.com/prototypal.html (specifically, the 2008-04-07 update).


If I am reading this right, then you can get efficiency gains by attaching methods to an object's prototype rather than defining them directly in a constructor. This way, the method is only created once, and is just reference by all instances of whatever object.

If I am correct about all that, my point of confusion is simply that this seems like a very awkward way to design things. Isn't it easier to read a program if all of an object's properties and methods are defined together in it's constructor, rather than spread out later as attachments to a prototype?


I haven't come across cases where I was forced to use prototypes. Can someone describe a situation where it would be necessary to use prototype? Or even advisable to use prototype?


Part of the problem with JavaScript is that prototypes are an inherent part of the language, but wrapped up behind syntactic sugar that hides them away on the fringes of the language.

If you've created an object in JavaScript, you've used prototypes, just indirectly.

If you want to use inheritance in Javascript prototypes are where it's at.

The ObjectName.prototype.fn = function() {} pattern is also a more memory efficient way of defining object methods than doing function ObjectName() {this.fn = function() {}}, as the method is only defined once in the former case, but is defined every single time a object is created in the latter case.

Basically for the most part you don't have to use prototypes directly, but more you know about them the better.


If you've ever used jQuery, you've used prototypes directly. For example, with $("a").click(), "click" is a function on the jQuery object's prototype; ie, $.prototype.click . Since you're likely to have multiple jQuery objects in a script, it makes sense performance wise for all those functions to be on the prototype instead of properties of a newly created object every time you instantiate that object.


Any time you want to use OO abstractions, share methods between many objects, inheritance, encapsulate related actions, etc. You can do purely functional programming in JS, but more complex projects require OO least they turn into spaguetti.


I'm with you. This is one of those things people use because it's there, which is how we get Everests of complexity.


Looks similar to Lua's metatables with __index property


Yes, Lua is a prototypal language too.


marked 'to read this weekend'. looks very interesting.


Cool! When do we get a NodeJS binding? XD




Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: