JavaScript Prototypes Made Easy
javascriptweblog.wordpress.com
javascriptweblog.wordpress.com
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)
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?
[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.
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.
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.
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.
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
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
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.
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.
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.
Here's a nice paper about it: http://ranger.uta.edu/~nystrom/courses/cse3302-fa10/selfPowe...
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?
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.