Object Oriented Programming with JavaScript


As we already know, JavaScript is an object oriented language. In this article we will see JavaScript example to inheritance and subtype polymorphism.
For solid base, I really recommend to read first about JavaScript Prototype.

Base Class

Lets define an Animal class. First thing to do is to define it’s constructor:

Animal constructor
var Animal = function() {  
    this.color = "Pink";
};

Next, lets define Animal’s methods:

Animal methods
Animal.prototype.run = function() {  
    console.log("Wuuuuuuuuuuuuushhhhhh");
};
Animal.prototype.sleep = function() {  
    console.log("ZZZzzzZZZzzzZZZzzzzzz...");
};
Animal.prototype.eat = function() {  
    console.log("HmnmnmHmmnmnm..BURP");
};

An easy way to write this is to extend Animal.prototype (using jQuery, underscore or your own implementation):

Animal methods using jQuery.extend
$.extend(Animal.prototype, {
    run: function() {
        console.log("Wuuuuuuuuuuuuushhhhhh");
    },
    sleep: function() {
        console.log("ZZZzzzZZZzzzZZZzzzzzz...");
    },
    eat: function() {
        console.log("HmnmnmHmmnmnm..BURP");
    }
});

Great, this looks better. Now we can create animals that can run, sleep and eat.

Sub Class – Inharitance

Lets create a Cat which is a sub class of an Animal. First create Cat’s constructor:

Cat constructor
var Cat = function() {  
    Animal.apply(this, arguments); // Call parent class constructor

    this.name = name;
    console.log("My name is " + this.name +
                " and my color is " + this.color);
};

Next, we want Cat to have Animal’s methods, so we need something like:

Cat’s prototype gets Animal’s prototype
Cat.prototype = Animal.prototype;

But this code will cause a problem. Adding new methods to Cat’s prototype will add those methods also to Animal (since Cat.prototype and Animal.prototype are now refrence to the same set of methods).
There are a few ways to solve this problem:

  1. Use Object.create method that creates an object based on set of properties:

    Using Object.create
    Cat.prototype = Object.create(Animal.prototype);
  2. Use extend:

    Using extend
    $.extend(Cat.prototype, Animal.prototype);
  3. Dance a little:

    Dancing
    var sub = function() { };  
    sub.prototype = Animal.prototype;  
    Cat.prototype = new sub();

Lets add methods to Cat:

Add methods to Cat
$.extend(Cat.prototype, {
    drinkMilk: function() {
        consoloe.log("lplplplplplp");
    },
    fightOtherCat: function() {
        console.log("Mirrrrrrrccchhhhh");
    }
});

Finally, Cat definition looks like this:

Cat definition
var Cat = function() {  
    Animal.apply(this, arguments);

    this.name = name;
    console.log("My name is " + this.name +
                " and my color is " + this.color);
};
Cat.prototype = Object.create(Animal.prototype);  
$.extend(Cat.prototype, {
    drinkMilk: function() {
        console.log("lplplplplplp");
    },
    fightOtherCat: function() {
        console.log("Mirrrrrrrccchhhhh");
    }
});

So, meybe it will be easier to create inheritance helper:

Inheritance helper
function inherit(base, methods) {  
    var sub = function() {
        base.apply(this, arguments); // Call base class constructor

        // Call sub class initialize method that will act like a constructor
        this.initialize.apply(this, arguments);
    };
    sub.prototype = Object.create(base.prototype);
    $.extend(sub.prototype, methods);
    return sub;
}

Now creating Cat using the new helper is really simple and clear:

Cat definition using our inheritance helper
var Cat = inherit(Animal, {  
    initialize: function(name) {
        this.name = name;
        console.log("My name is " + this.name +
                    " and my color is " + this.color);
    },
    drinkMilk: function() {
        console.log("lplplplplplp");
    },
    fightOtherCat: function() {
        console.log("Mirrrrrrrccchhhhh");
    }
});

Sub Class – Subtype Polymorphism

Since cats are purring when they sleep, lets override the sleep method:

Override base class method
var Cat = inherit(Animal, {  
    ...
    ...
    ...
    sleep: function() {
        console.log("rrr...rrr...rrr...");
    }
});

But, what if after purring, cats getting sleep like any other animal?
Lets call the Animal’s sleep method right after purring:

Calling base class method
var Cat = inherit(Animal, {  
    ...
    ...
    ...
    sleep: function() {
        console.log("rrr...rrr...rrr...");
        Animal.prototype.sleep();
    }
});

Now out cat will sleep like any other animal after purring a little.

Complete Code

Here is our complete code:

Complete code
function inherit(base, methods) {  
    var sub = function() {
        base.apply(this, arguments); // Call base class constructor

        // Call sub class initialize method that will act like a constructor
        this.initialize.apply(this, arguments);
    };
    sub.prototype = Object.create(base.prototype);
    $.extend(sub.prototype, methods);
    return sub;
}

var Animal = function() {  
    this.color = "Pink";
};
$.extend(Animal.prototype, {
    run: function() {
        console.log("Wuuuuuuuuuuuuushhhhhh");
    },
    sleep: function() {
        console.log("ZZZzzzZZZzzzZZZzzzzzz...");
    },
    eat: function() {
        console.log("HmnmnmHmmnmnm..BURP");
    }
});

var Cat = inherit(Animal, {  
    initialize: function(name) {
        this.name = name;
        console.log("My name is " + this.name +
                    " and my color is " + this.color);
    },
    drinkMilk: function() {
        consoloe.log("lplplplplplp");
    },
    fightOtherCat: function() {
        console.log("Mirrrrrrrccchhhhh");
    },
    sleep: function() {
        console.log("rrr...rrr...rrr...");
        Animal.prototype.sleep();
    }
});

Usage

Since I have a cat, I must create its virtual persona:

My virtual Mutzi
var mutzi = new Cat("Mutzi");  
mutzi.run();  
mutzi.fightOtherCat();  
mutzi.sleep();

And of course, the result will appear on the console:

My virtual Mutzi
My name is Mutzi and my color is Pink  
Wuuuuuuuuuuuuushhhhhh  
Mirrrrrrrccchhhhh  
rrr...rrr...rrr...  
ZZZzzzZZZzzzZZZzzzzzz...

Summary

In this article we created the Animal base class. Then we created the Cat sub class by inherit from Animal. Then we added new methods for Cat and at the end we overridden Animal’s method and used the base class implementation in our implementation.

I hope you had fun reading this article!
Any questions -> to me 🙂

  • dxcqcv

    I found base.call(this, arguments) and sub.prototype = Object.create(base) can be merge with sub.prototype = new base(); , it’s work , but I dont know whether it has any drawback

  • djarumsuper

    very good and funny tutorial for intro to OOP JS! well done!

  • Pratik Barasia

    Just wanted to point out a small mistake in code block “Cat definition”. You have written this.name=name, but name is not passed in to the constructor function anywhere.

  • great !

  • Giannis Stamoutsos

    Top! Excellent explanation