Object Oriented JavaScript – Part 2

by Prasanth Gullapalli

In any object oriented language, inheritance can be achieved in two ways: 1. Interface Inheritance 2. Class Inheritance. JavaScript don’t have support for the former but supports the latter through the use of Prototype Chaining. So it is very vital to understand what Prototype Chaining is.

1. Prototype Chaining
Recall from the previous article that properties/functions defined on prototype are available to all the instances of the function(reference type) created using new keyword and prototype will internally have a reference to the constructor. This characteristic will be used to achieve Inheritance in JavaScript.

function Parent(){
	this.parentProperty = 'Property in Parent';
}

Parent.prototype.getParentPropertyValue(){
	return this.parentProperty;
}

function Child(){
	this.childProperty='Property in Child';
}

// Inherit from SupertType
Child.prototype = new Parent();
Child.prototype.getChildPropertyValue(){
	return this.childValue;
}

var childObj = new Child();
alert(childObj.getParentPropertyValue()); // Property in Parent
alert(childObj.getChildPropertyValue());// Property in Child

childObj.getParentPropertyValue() works because when you call a property on an instance created using new operator, the search happens on the instance own properties, if not found then goes up to search in the object’s prototype own properties. If not found there too, it searches the prototype of prototype and the search continues higher up the chain till the Object prototype is reached. If at any level the property is found, the search is stopped and the property value is returned. As the search continues up higher and higher the prototypes, this is called Prototype chaining. Because of prototype chaining, the object created above becomes instance of all the classes involved in the prototype chain.

alert(childObj instanceof Object); //true
alert(childObj instanceof Parent); //true
alert(childObj instanceof Child); //true

Note that any object created through new operator will get access to the functions defined on the Object’s prototype. Here are few of the methods defined on the Object prototype: hasOwnProperty, isPrototypeOf, propertyIsEnumerable, toString and valueOf.

alert(Object.prototype.isPrototypeOf(childObj)); //true
alert(Parent.prototype.isPrototypeOf(childObj)); //true
alert(Child.prototype.isPrototypeOf(childObj)); //true

Recall from the earlier article that it is good practice to define object properties inside the constructor and methods on the prototype. But when implementing inheritance using prototype chaining, we define parent object to be the prototype of child object. Hence properties defined in the constructor of parent becomes properties of the child prototype. Here is the exact scenario:

function Parent(){
	this.sampleArray = ['X'];
}

Parent.prototype.getArray(){
	return this.sampleArray;
}

function Child(){
}

// Inherit from SupertType
Child.prototype = new Parent();

var instance1 = new Child();
var instance2 = new Child();
instance1.getArray().push('Y');
alert(instance1.getArray()); // X, Y
alert(instance2.getArray()); // X, Y

This is the major problem with prototype chaining. We don’t want properties of instance2 to be modified. This can be resolved by using Constructor Inheritance

2. Constructor Inheritance: This is in fact called as Constructor stealing. Here is how you implement it:

function Parent(property1, property2){
	this.sampleArray = ['X'];
	this.property1 = property1;
	this.property2 = property2;
	this.alertProperty1 = function(){
		return this.property1;
	}
}
function Child(property1, property2, property3){
	// Inherit properties from Parent.
	// Call Parent as function by binding 'this' to it
	Parent.call(this, property1, property2);
	this.property3 = property3;
}

Here we are not instantiating instance of Parent. We are rather invoking it as function by binding instance of Child as ‘this’ in it. So all the properties defined on Parent gets bound to ‘this’ which is instance of Subtype. Now what is output of the following?

var child1 = new Child();
child1.sampleArray.push('Y');
alert(child1.sampleArray); // X, Y

var child2 = new Child();
alert(child2.sampleArray); // X

Points to note:
(i) In Prototype chaining, we will never invoke the Parent constructor and hence can not pass any arguments to it. But here we can do it.
(ii) In the example above, for both child1 and child2 gets different function instances for alertProperty1
alert(child1.alertProperty1 == child2.alertProperty1) // false
(iii) Properties defined on constructor of Parent never gets copied.

The constructor inheritance thus solved the problem that we faced with Prototype Chaining. But this shares the same problem of objects creation with Constructor pattern we discussed in the last article. This problem can be solved by combining Constructor Inheritance with Prototype Chaining.

3. Combination Inheritance: Here is how we do it:

function Parent(property1, property2){
	this.sampleArray = ['X'];
	this.property1 = property1;
	this.property2 = property2;
}

Parent.prototype={
	constructor:Parent,
	alertProperty1 = function(){
		return this.property1;
	},
	alertProperty2 = function(){
		return this.property2;
	}
}

function Child(property1, property2, property3){
	// Inherit properties from Parent.
	// Call Parent as function by binding 'this' to it
	Parent.call(this, property1, property2);
	this.property3 = property3;
}

Child.prototype = new Parent();
Child.prototype.alertProperty3 = function(){
	return property3;
}

var child1 = new Child('A', 'B', 'C');
var child2 = new Child('P', 'Q', 'R');
alert(child1.alertProperty1 == child2.alertProperty1); // true
alert(child1.alertProperty2 == child2.alertProperty2); // true
child1.alertProperty1(); // A
child2.alertProperty1(); // P

Here what actually happens when we call alertProperty1 on child1?
JavaScript Engine checks whether child1 has function ‘alertProperty1’ defined on it. As it is defined, it calls this function(as we called Parent() by binding ‘this’ which is of child type). But note that there is also ‘alertProperty1’ function defined on the prototype of Parent. But this would never be called as it exists on the child object directly.

This type of inheritance is so far the best way of implementing Inheritance. There are few more ways of implementing inheritance which we will discuss in the next article of this series.

Advertisements

5 thoughts on “Object Oriented JavaScript – Part 2

  1. On the first code in this page, at line 14, you wrote,
    “Child.prototype = new SuperType();”
    but you mean
    “Child.prototype = new Parent();”
    right?

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s