14. Mai 2009

Javascript Inheritance

Javascript is one of the coolest languages. What a pity, that the world needed 10 years to grok the concept of a prototype-oriented language. I have a deep respect for the inventor(s) and/or the one who chose the concept for Netscape Navigator 2.0. In the first years after 1996 most Javascript/DHTML programmers used it as a spaghetti code scripting language with global functions.

Later the world turned to use Javascript as an object-oriented language trying to emulate object-oriented inheritance with JS methods. There were many ways to do this. I used several over time. You always try to harmonize the coding style at least in a project. But there is a drift. Some time ago I proposed a OO-inheritance style as guideline for all JS coding in the company. Allan, being a JS wizard, could improve on it and we developed my latest OO-inheritance style for Javascript. The concept basically copies the prototype properties to the derived class using:

// Base class:
function Animal(param1) {}
// Derived class
Dog.prototype = {}; for (_ in Animal.prototype) { Dog.prototype[_] = Animal.prototype[_]; }

This is not as Allan would use it, because leaving the '_' variable in the global scope is bad style. We could encapsulate the transfer of prototype properties into a function, but that leaves a function in the global scope. Still, this can be regarded as more beautiful, so we get in full beauty:

// Prototype copy utility (beware, this is a long line)
window.deriveClass = function(baseClass, derivedClass) { derivedClass.prototype = {}; for (var i in baseClass.prototype) { derivedClass.prototype[i] = baseClass.prototype[i]; derivedClass.prototype.baseClass = baseClass; }};

// Base class:
function Animal(param1)
this.a = param1;
Animal.prototype.getClass = function() { return 'Animal'; }

// Derived class
window.deriveClass(Animal, Dog);
function Dog(param1, param2)
this.baseClass.call(this, param1);
this.b = param2;
Dog.prototype.getClass = function() { return 'Dog'; }

The function window.deriveClass also adds a prototype property baseClass so, that the Dog constructor can use it to initialize the base class without using 'Animal' explicitly. See the example.

Before that I used a shorter, but more dirty way to subclass, which calls the base class constructor once without parameters:

Dog.prototype = new Animal;


Kommentar veröffentlichen