Object-Oriented Javascript – Simple Definition and Inheritance

For some reason, I’ve recently become enamored of the idea of Object-oriented Javascript (OOJS).  Probably because I’ve been wrestling with the strongly-typed complexities of C# / Visual Studio after having been working for so long with the more relaxed PHP, and the quick-and-dirty nature of Javascript is so appealing.  Plus you don’t need any complicated development environments to play with it!

That being said, I was recently at a great Meetup where we talked about OOJS and code structuring tips, which built upon what I had just read by these fantastic articles:

Basic object-oriented principles in JS and its followup regarding inheritance, and another inheritance helper from one of the jQuery guys.

I thought I’d take a stab at it with the following fiddle: http://jsfiddle.net/9CUGG/6/

I went for a very simplistic, contained, and easy to use method to define and inherit classes.  The important parts are the Define and Inherit functions.

// helper macro to assist in class definition
Define = function(Class, methods) {
    for(var method in methods) {
        // only explicitly defined methods
        if( methods.hasOwnProperty(method) ) {
            Class.prototype[method] = methods[method];
        }
    }
    
    return Class;
};

This lets you easily define a class and attach public methods (vs private or privileged) like so:

// sample class with privileged and/or private properties
function Car(name) {
    var randomIdentifier = (new Date()).getMilliseconds();
    this.name = name || "Car " + randomIdentifier;
    this.wheels = 4;
    this.color = "red";
}

// attach methods to prototype; note that private not accessible
Define(Car, {
    drive: function(){
        _log('driving on '+this.wheels+' wheels: ', this.name);
    }
    ,
    showColor: function(){
        _log( this.name, ' is ', this.color );
    }
    ,
    showName: function(){
        _log('My car is ', this.name);
    }
});

where line 2 is a “regular class” definition with privileged and private properties, and line 9 defines class-wide public methods shared among all instances of Car.

We can then instantiate new car objects and use their functionality with:

// instantiate
var mycar1 = new Car();
var mycar2 = new Car('Miata');

// implement
mycar1.showName();     // >> My car is Car 574 
mycar1.showColor();    // >> Car 574 is red 
mycar1.drive();        // >> driving on 4 wheels: Car 574 
mycar2.showName();     // >> My car is Miata 
mycar2.showColor();    // >> Miata is red
mycar2.drive();        // >> driving on 4 wheels: Miata
// helper macro to assist in inheritance; via http://phrogz.net/js/classes/OOPinJS2.html
Inherit = function(parentClass, initialDefinition) {
    var childClass = initialDefinition || function() {}
    childClass.prototype = new parentClass(); // where the inheritance occurs 
    childClass.prototype.constructor = childClass; // Otherwise instances of child would have a constructor of parent
    childClass.prototype.parent = parentClass.prototype; // expose super
    return childClass;
};

Note that in line 3, if you don’t specify the “constructor” you get a blank object, as opposed to automatically inheriting the parent’s. I think Resig’s .init trick gets around this.

So, you then inherit like so:

// instead of:  Suv = Object.create(Car);
Suv = Inherit(Car, function Suv(name) {
    this.name = name || "Car " + (++Uid);
    this.wheels = 4;
    this.color = "brown";
});

which lets you re-/define public Suv methods and instantiate objects as before.

Check out the full source at the fiddle, play around, and let me know what you think!

(And, I know I could attach Define and Inherit to the Function prototype, but I left them separate for this example.)

One thought on “Object-Oriented Javascript – Simple Definition and Inheritance

Leave a Reply

Your email address will not be published. Required fields are marked *