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.



https://outof.me

Post a comment

You may use the following HTML:
<a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <s> <strike> <strong>