JavaScript – A Different Beast, Part-7: Inheritance without Classes

An example of inheritance: Domain model for a State-Chart diagramming tool

The domain model for a simplistic state-chart diagramming tool would look as in figure below.

Class diagram for a State Machine Model

Class diagram for a State Machine Model

Code below shows an implementation of this hierarchy in JavaScript.

//constructors
function StateChartElem(){
	this.setName = function(name) {
		this.name = name;
	}
	this.setLabel = function(label) {
		this.label = label;
	}
}

function State(){
	this.setType = function(type){
		this.type = type;
	}
}

function Transition(){
	this.setPreCondition = function(c){
		this.preCondition = c;
	}
	this.setSource = function(src){
		this.src = src;
	}
	this.setTarget = function(tgt){
		this.tgt = tgt;
	}
}

function StateChart() {
	this.elems = new Array();
	this.addElem = function(elem){
		this.elems.push(elem);
	}
}

//setting up the prototype chains
var stateChartElemProt = new StateChartElem();
State.prototype = stateChartElemProt;
Transition.prototype = stateChartElemProt;
var stateProt = new State();
StateChart.prototype = stateProt;

//instantiating a state chart
var state1 = new State();
var state2 = new State();

console.log(state1.__proto__ === stateChartElemProt); //true
console.log(state1.__proto__ === state2.__proto__); //true

state1.setName('state1');
state1.setLabel('State-1');
state1.setType('Initial');

state2.setName('state2');
state2.setLabel('State-2');
state2.setType('Final');

console.log(state1); //StateChartElem { name="state1", label="State-1", type="Initial"}
console.log(state2); //StateChartElem { name="state2", label="State-2", type="Final"}

//creating transitions
var trans1 = new Transition();
trans1.setName('trans1');
trans1.setLabel('Transition-1');
trans1.setPreCondition('x==10');
trans1.setSource(state1);
trans1.setTarget(state2);

console.log(trans1);//StateChartElem { name="trans1", label="Transition-1",preCondition="x==10"}

//setting up chart
console.log('Creating StateChart');
var chart1 = new StateChart();
chart1.setName('chart1');
chart1.setLabel('Example State Machine');
chart1.addElem(state1);
chart1.addElem(state2);
chart1.addElem(trans1);

console.log(chart1);//StateChartElem { elems=[3], name="chart1", label="Example State Machine"}

Previous code is the true JavaScript way of doing things – so called ‘thinking in JavaScript’ approach. This approach doesn’t work half as nice when your constructors take parameters. Try introducing parameters and see for yourself. Code below shows another way of doing it, this time without using the prototypes. The key technique in play here is a behavior of the this variable that it always points to the current object when invoked from a member method.

//constructors
function StateChartElem(name,label){
	this.setName = function(name) {
		this.name = name;
	}
	this.setLabel = function(label) {
		this.label = label;
	}
	this.setName(name);
	this.setLabel(label);
}

function State(name,label,type){
	this.setType = function(type){
		this.type = type;
	}
	this.setType(type);
	this.super = StateChartElem; //attached  the base constructor as a method to this object. 'super' is not a keyword.
	this.super(name,label); // invoking the method constructs its members within the state object since 'this' points to state object inside this method
}

function Transition(name,label,preCondition){
	this.setPreCondition = function(c){
		this.preCondition = c;
	}
	this.setSource = function(src){
		this.src = src;
	}
	this.setTarget = function(tgt){
		this.tgt = tgt;
	}
	this.daddy= StateChartElem; //not called 'super' here.  'daddy ' works fine too.
		this.daddy(name,label);
	}

function StateChart(name,label) {
	this.elems = new Array();
	this.addElem = function(elem){
		this.elems.push(elem);
	}
	this.super = State;
	this.super(name,label,'Composite');
}

//instantiating a state chart
var state1 = new State('state1','State-1','Initial'); //no complicated prototype chaining
var state2 = new State('state2','State-2','Final');

console.log(state1); //State { name="state1", label="State-1", type="Initial"}
console.log(state2); //State { name="state2", label="State-2", type="Final"}

//creating transitions
var trans1 = new Transition('trans1','Transition-1','x==10');
trans1.setSource(state1);
trans1.setTarget(state2);
console.log(trans1);// Transition { name="trans1", label="Transition-1",preCondition="x==10"}
//setting up chart
console.log('Creating StateChart');
var chart1 = new StateChart('chart1','Example State Machine');
chart1.addElem(state1);
chart1.addElem(state2);
chart1.addElem(trans1);
console.log(chart1);// StateChart { elems=[3], name="chart1", label="Example State Machine"}

Next topic: Arrays, Maps and the for..inloop

Further Reading:

  1. https://javascriptweblog.wordpress.com/2010/06/07/understanding-javascript-prototypes/ . This is what you should read if you need to know more about JavaScript’s prototype. All the explanations found elsewhere will only add to your confusion.
  2. http://mckoss.com/jscript/object.htm. A detailed explanation on prototypal inheritance.
  3. http://javascript.crockford.com/prototypal.html. A brief but insightful foray into prototypes.
  4. http://citeseerx.ist.psu.edu/viewdoc/summary?doi=10.1.1.56.4713, Prototypes vs. Classes – Some Philosophical and Historical Observations, Antero Taivelsari, Journal Of Object Oriented Programming, 1996. Read this to understand the philosophical reasoning behind class-less object orientation.
  5. https://developer.mozilla.org/en/Differential_inheritance_in_JavaScript, Differential Inheritance in JavaScript.
  6. https://developer.mozilla.org/en/Core_JavaScript_1.5_Guide/Details_of_the_Object_Model, Details of the Object Model. Detailed (not in-depth) explanation of object orientation in JavaScript with elaborate examples and comparison with classical object orientation
  7. http://ejohn.org/apps/learn/. An excellent interactive tutorial from John Resig himself. It has only code and no explanations. Should be read along with his book.
Advertisements

About Rahul Mohan

Technical researcher interested in model-driven development of enterprise business applications. Passionate about web technologies and a huge admirer of open-source especially in the Java landscape. When I am not doing any of the above you can find me with my camera (www.flickr.com/photos/rahulmohan/) or listening to music. (In fact, the title of the blog is inspired by Led Zeppelin's Physical Graffiti. )

Posted on June 13, 2011, in JavaScript, Tutorial and tagged , , , , , , . Bookmark the permalink. Leave a comment.

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

%d bloggers like this: