Javascript / Inheriting the “DNA” vs. mixing behaviour


The inheritance approaches in Javascript are discussed quite often. The most people, especially Java developer (me too?), have troubles with proper usage of the inheritance.

There are 3 approaches:

  • prototypical inheritance: this is actually the javascript way
  • functional inheritance: is about mixing objects into other objects
  • classical inheritance: IMHO, this approach doesn’t exist. It can be simulated but it’s not real.

I. The prototypical pattern (see David Crockford’s prototypical inheritance, http://javascript.crockford.com/prototypal.html) looks like follows:

function S() {};

function F() {};
F.prototype = new S();
var myObj = new F();

An object created this way is recognized as instance of S and F as well.

Look at this example. d is a Dog, a Mammal and a Being because the Javascript interpreter climbs the prototype chain when using instanceof operator. I call this approach “inheriting the DNA”. The object is born and it knows everything about it’s origin.

js_simple_prototyping

////// Being
function Being() {};

///// Mammal

function Mammal() {};
Mammal.prototype = new Being();
Mammal.prototype.constructor = Mammal;

function Dog() {};
Dog.prototype = new Mammal();
Dog.prototype.constructor = Dog;
var d = new Dog();

console.log( d instanceof Dog );      //true!!
console.log( d instanceof Mammal );   //true!!
console.log( d instanceof Being );    //true!!

II. The functional pattern is about mixing properties and methods into objects.

Instead of using prototype keyword, the properties are just copied into the target object. The resulting object doesn’t know something about the origin of the copied properties. Therefore, m instanceof Being returns false.

Why might we use this pattern? Because javascript doesn’t support multiple inheritance! See also this post for further information: http://stackoverflow.com/questions/7264370/multiple-inheritance-question/7265248#7265248

js_multiple_inheritance_not_poss

Take a look at the following example. m : Mammal inherits from b : Being but it doesn’t know anything about it.

function extend(from,to) {
	for( var a in to )
		from[a] = to[a];
}

function Being() {
}

function Mammal() {
}

var m = new Mammal();
extend(new Being(),m);
console.log( m instanceof Mammal );   //true!!
console.log( m instanceof Being );    //false!!

Here is also a more complicated example which provides a combination between prototypical and functional inheritance because it builds a mixed object and assigns it finally to the prototype property of the target object.

function A() {
    this._a = function() {
        return "_a";
    }
};
A.prototype.a = function() {
    return "a";
};

function B( firstName, secName ) {
    var self = this.inherit(A);
    this._b = function() {
        return "_b";
    }
    return self;
};

B.prototype.b = function() {
    return "b";
};


function C() {
    var self = this.inherit([B,A]);
    this._c = function() {
        return "_c";
    }
    return self;
};
C.prototype.c = function() {
    return "c";
};

if( typeof Object.prototype.inherit == 'undefined' ) {
    Object.prototype.inherit = function( clazzes ) {
        if( clazzes.constructor !== Array )
            clazzes = [clazzes];

        var prot = this;
        for( var i=0; i<clazzes.length; i++ ) {
            var clazz = clazzes[i];
            var constr = clazz.prototype.constructor;
            var c = new constr();
            for( var a in c )
                prot[a] = c[a];
        }
        var constr = this.__proto__.constructor;
        this.prototype = prot;
        this.__proto__.constructor = constr;
        return this;
    }
}

var c = new C();

console.log( c._c() );
console.log( c.c() );
console.log( c._b() );
console.log( c.b() );
console.log( c._a() );
console.log( c.a() );
console.log( c instanceof A );
console.log( c instanceof B );
console.log( c instanceof C );
Advertisements

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