Saturday, July 28, 2012

Inheritance in JavaScript

We all say we can have object oriented way of implementation in JavaScript. So lets see how can we inherit one class from another in JavaScript. In C# is very easy, writing a ":" will do it for you, but in JavaScript it is little tricky. We all know about prototype and constructor in java script(if you don't know please clear this concept from my previous post 'JavaScript tips and tricks -4'). In very simple words prototype gives you the instance of the base class and constructor gives you the instance of derived class.
Lets try to make inheritance between Pet and Dog class.
function Pet(name){
        this.getName = function(){return name;};
        this.setName = function(newName){name = newName;};
     }
function Dog(name, breed){
        this.getName = function(){return name;};
        this.getBreed = function() { return breed;};     
    }
Above code shows Dog constructor which takes name and breed as input and Pet constructor which takes name as input. Now we want to have toString method on Pet and Dog both. There are 2 ways to do it-
We can define it inside Class itself (perellel to this.getname method) or we can define it on prototype like this -
Pet.prototype.toString = function(){
        return "This pet Name is - " + this.getName();
    }
Dog.prototype.toString = function(){
        return "This is a Dog from prototype with NAme - " + this.getName() + " and Breed is - " + this.getBreed();
    }
If you remember from previous post how JavaScript execute any method on any object,you will understand the difference between 2 techniques.
Now lets put inheritance between these 2 classes -
    Dog.prototype = new Pet();
Now the prototype of Dog is a Pet, you can also call Dog as derived class of Pet.
Before we go into more detail of Dog and Pet, let me introduce one more property named as constructor.
consider another example -
function Person(){}
var p = new Person();
if(p.constructor === Person){
    alert('p.constructor === Person'); --> It will alert.
}
else{
    alert('p.constructor !== Person');
}
var p1 = new p.constructor();
if(p1 instanceof Person)
{
    alert('true'); --> TRUE
}
In the above example, if you see we created another object of Person using property constructor. Which means using constructor we can create object of same type, which can be proved once p1 instanceof Person alerts true. In order to achieve same objective we need to set the constructor property of Dog as well. But as we want this property to be there for all Dog objects, thus we will introduce it in the prototype function like this-
    Dog.prototype.constructor = Dog;
 If we dont set this property then we can't use this -
var dog1 = new dog.constructor();
It will not create another Dog object, instead it will create a Pet object, as constructor is available in Pet class.
If you remember inheritance in C#, whenever the object of derived class is initialized, its base class object need to initialized before that. The similar thing we will need to achieve in JavaScript as well to complete the inheritance. In order to do so, we can write call method of Pet in Dog constructor like this -
function Dog(name, breed){
        Pet.call(this, name);
        this.getBreed = function() { return breed;};      
    }
Now whenever a new Dog object is created it will automatically create Pet object as well. It completes our implementation of inheritance between Dog and Pet. Here is the full code -
    function Pet(name){
        this.getName = function(){return name;};
        this.setName = function(newName){name = newName;};
        //this.toString = function() {return "Pet with name " + this.getName();};
    }

    Pet.prototype.toString = function(){
        return "from prototype - This  pet Name is - " + this.getName();
    }

    var myPet = new Pet("pet1");
    alert(myPet);

    function Dog(name, breed){
        Pet.call(this, name);
        this.getBreed = function() { return breed;};
        //this.toString = function() {return "Dog with name " + this.getName();};
    }

    Dog.prototype = new Pet();
    Dog.prototype.constructor = Dog;

    Dog.prototype.toString = function(){
        return "This is a Dog from prototype with Name - " + this.getName() + " and Breed is - " + this.getBreed();
    }
    var dog = new Dog("Dog1", "Breed 1");
    alert(dog);

    alert(dog instanceof Dog);//true
    alert(dog instanceof Pet);//true
    alert(dog instanceof Object);//true
In order to check if inheritance was successful or not, you can always use "instanceof" method which gives true if the object is instance of given type.

Dog.prototype return object of Pet, which is base class for Dog.
constructor property returns you the constructor of that class. For example -
in above example dog.constructor does return constructor of Dog. It always possible to create another object (say dog1) of Dog using
var dog1 = new dog.constructor('dog2','breed2');

prototype can also used to modify existing object. For example we can add new method in inbuilt Array class -
if (!Array.prototype.forEach) {
  Array.prototype.forEach = function(fn){
    for ( var i = 0; i < this.length; i++ ) {
      fn( this[i], i, this );
    }
  };
}
var myArray = new Array('a', 'b', 'c');
myArray.forEach(function(value, index, array){
  alert(value + "-" + index + "-" + array)
});

Namespace in JavaScript-
JavaScript does support the namespaces. It helps us to avoid name collision. Here are some examples-
var namespace1 = {};
namespace1.var1 = function() {};
namespace1.var1.prototype.toString = function(){};

We can have multilevel namespaces also -
var namespace1 = {}
namespace1.namespace2 = {};
namespace1.namespace2.var1 = function(){};

No comments:

Post a Comment