Saturday 12 February 2011

My Favourite (i.e. the best) Javascript OOP inheritance method

The refactoring is mostly complete and I thought I would discuss the inheritance method I've decided to use.  It's probably fairly similar to the one in the Prototype library.  To understand this you probably need a base understanding of the differences between an Object, a 'Class' and a Function.  Along with knowledge of prototype based OOP.  I might do a simple post on that later if I get inspired.


jObjective.Class = function() {
    var constructor = function() {
        this.initialize.apply(this, arguments);
    }


    var base = arguments[0];


    if (arguments.length == 1) {
        constructor.prototype = base;
    } else {
        var inherited = arguments[1];
        var type = new base;
        
        for (var prop in inherited) {
            var temp = inherited[prop]
            if (temp !== undefined) {
                type[prop] = temp;
            }
        }
        constructor.prototype = type;
    }


    return constructor;
}


That's the function I'm using to create the inherited and base classes.  The possible arguments are 

  • 1 single argument: Takes an object as the parameter and creates a class from it.
  • 2 arguments: The first parameter is the base class and the second parameter is the object which will inherit from the base.
Now lets go through it.  For example, here is a snippet of the DataObject class:

jObjective.DataObject = jObjective.Class({
    initialize: function(jObject) {}});

The Class function takes a single object as the parameter, i.e. {
    initialize: function(jObject) {}}

The Class function then declares the constructor function, which simply calls the initialize method of which ever parent object it happens to reside in.

The object parameter then becomes the prototype of the constructor allowing us to create new instances of it (i.e. the basis of prototype oop).  The constructor, which is now a full 'class' is then returned.  

For the second example, here is a snippet of the DataElement class:

jObjective.DataElement = jObjective.Class(jObjective.DataObject, {});

The Class function now takes the DataObject class as the first parameter and the DataElement object as the second parameter.  To create a class which inherits from DataObject and then implements DataElement, we need to first set the prototype of the constructor to the DataObject, then implement all of the methods in the DataElement in that same prototype.  This can be done by simply applying each of the properties onto the prototype (as it was done in the first version of jObjective), but this is limiting because the constructors cannot be inherited and have to be rewritten every time.  What the Class function does is simply iterate through each of the properties and apply them to the prototype (which is now the DataObject prototype), thereby extending it.  


The extended class is now returned and we can create instances of it.

This is a very rudimentary extend method and I know there are some issues with it (toString in IE is one property that doesn't get extended correctly), but at this point it does everything that jObjective needs, so I don't want to add any more overhead into constructing the classes. 

Hope that makes sense.

No comments:

Post a Comment