JavaScript Prototypal inheritance for class’ical developers
Developers who are learning JavaScript and have prior experience with strongly typed classical languages like Java, C#, or C++ often have trouble using the JavaScript inheritance model. Some even think that JavaScript doesn’t support inheritance at least that’s what I thought when I first learned it. Well, I was completely wrong!
A couple of days ago I started the process of componentization for a part of an app that I was working on. During that task I wanted to remove a reference to Backbone.js, which mimics the class’ical inheritance model in JavaScript. Because of that I had to dig deeper than before and understand how I could use pure prototypal inheritance without any third-party frameworks or libraries. So below you can see a solution that I discovered at many blogs, forums, and other docs covering this topic. I believe this is the cleanest solution that doesn’t require any third-party code to include in your apps.
The snippet below defines a base Parent
type that other types in the following snippets will inherit from. It is specified as a function that will be a constructor for a new objects. It also specifies a funA
function that can be overridden in descendent types.
// ******* DEFINING PARENT TYPE ******* var Parent = function(a) { // Setting type instance level properties this.a = a; }; // Defining funA function that will be inherited by descendant types Parent.prototype.funA = function() { // Parent.funA code... };
The snippet below defines a Child
type that inherits from Parent
type. The inheritance is done in two steps, first by calling the Parent
constructor function using Parent.call(this, a)
and second by setting the prototype
property to a new object with a prototype
property from the Parent
type (in this case I used the new Object.create()
function that is specified in ECMAScript5; IMHO this approach is preferable to creating a new instance of Parent
type because this way the Parent
type constructor function is not called unnecessarily).
// ******* DEFINING CHILD TYPE ******* var Child = function(a, b) { // Calling parent type constructor function Parent.call(this, a); // Setting type instance level properties this.b = b; }; // This will give Child access to Prent functions // Object.create() function requires ECMAScript5 compatible browser, // if this is not supported just a new instance of Prent type could be used instead Child.prototype = Object.create(Parent.prototype); // Defining funB that will be only available for Child type instances Child.prototype.funB = function() { // Child.funB code... };
This last snippet demonstrates how you can override ancestor functions; in this case the funA
function is overridden. The GrandChild.funA()
implementation demonstrates also how to make calls to the ancestor type funA
function.
// ******* DEFINING GRANDCHILD TYPE ******* var GrandChild = function(a, b, c) { // Calling parent type constructor function Child.call(this, a, b); // Setting type instance level properties this.c = c; }; // This will give GrandChild access to Parent and Child functions through a prototypes chain GrandChild.prototype = Object.create(Child.prototype); // Overriding ParentType.funA function GrandChild.prototype.funA = function() { // Calling overridden funA function Parent.prototype.funA.call(this); // GrandChild.funA code... };
Hope this post will be useful for those of you who are switching from a class’ical inheritance model. One last comment and some advice for those that like to bash JavaScript for different things. Before doing so first try to understand how prototypal languages work and don’t try to use them in a way they were not designed to work.
If you want to experiment further with the example above you can check it out on JSFiddle.