Prototypal inheritance isn’t terribly difficult to get started using for simple things, but it gets increasingly difficult (and difficult to understand) when you try to move beyond simple. Looking at the example below (courtesy of Nicholas Zakas because I was too lazy to write my own simple code), when creating the
Animal type, you see some oddness, but once you get over that, it’s not difficult. For instance, to create the constructor, we just make a function name
Animal. That’s odd, but you get over it and it’s not much of a problem. The only real problem here is that unless everyone follows conventions correctly, it’s difficult to know when someone is just writing a function or if they’re writing a constructor. Conventions in naming help, though.
Anyway, moving on, we see how to add a method to
Now we’re going to get to the troublesome area. In the code below, we’re going to create a type that inherits from
Dog. Two things stick out to me as “bad”. On line 2, we try to call the “super” constructor, but since there’s no
apply. While the existence of these two functions has started to become better known, they’re still an advanced feature that beginners are unlikely to know. It definitely took me a while to learn about them. In any case, it isn’t elegant.
The second nuisance comes from trying to establish the inheritance, which is done with this code below:
Dog.prototype = new Animal(null);. Even now, this code doesn’t make a whole lot of sense to me. I understand what’s going on, but creating an instance of a type so that you can inherit from it doesn’t make sense. Also a potential bug could show up if the
Animal constructor does anything besides initialize internal properties, such as DOM manipulation. All we’re trying to do is inherit from
Animal but to do so an
Animal is created and starts changing the page.
Because of these apparent problems, many libraries created their own way of handling this inheritance that simplifies it. There is nothing inherently wrong with the prototypal inheritance model. The problems come from the work required to do it and the misunderstanding that can come from its syntax.
If you came from a background with a classical OO language, wouldn’t this make perfect sense to you? It’s clear, concise, and simple. You get exactly what you think you’re getting. Also, though the syntax is new, there is actually nothing new going on here. It is still doing the same thing as before, just with cleaner code. There’s still prototype chaining, methods are still added to prototypes, you can still manipulate it the same way you did with the old syntax, but you don’t have to anymore.