Understanding prototypal inheritance in JavaScript - Part 2

In the previous installment of the prototypal inheritance series we have seen how a class-based object system works, now let's take a look at how to instantiate and initialize objects on a prototypal object system.

Instead of creating a class, in JavaScript you create directly an object.

Now, the JavaScript language has evolved over the years on how objects are created, you can see in many JavaScript programs a function that sets the properties of the this object, and gets called with the new operator, and the object methods are defined by extending the prototype property of the function. This is the old and complicated way of dealing with objects.

Instead of going through all that sort of complication, the easiest way of creating an object in JavaScript is to use the object literal notation:

var PRect = {
    init: function (options) {
        // Initialize the object
    },

    resize: function (options) {
        // Resize the rect
    },

    move: function (options) {
        // Move the rect
    }
};

This object is ready to use as it is, if we want:

PRect.move({centerx: 200});

but that's not the case here, as we want this object to be the prototype for other objects; let's call it a Prototype Object.

A couple more things to notice:

  • The name init is just a convention used by friGame for constructors, it is not enforced by the language
  • The P in the name PRect is a Hungarian Notation that stands for a Prototype Object (and yes, Hungarian Notation is a Good Thing), and also this is just a convention used by friGame

Now, let's do what would be instantiating the class in a class-based system:

var my_rect = Object.create(PRect);
my_rect.init({left: 0, top: 0, width: 100, height: 100});

Notice here that the object instantiation and initialization are 2 separate steps.

If we want to make it 1 step, as in the classical inheritance model, we can write a function like this:

function Rect() {
    var obj = Object.create(PRect);
    obj.init.apply(obj, arguments);

    return obj;
}

and then use it like this:

var my_rect = Rect({left: 0, top: 0, width: 100, height: 100});

Notice that the new operator is not used here, as this function is not different than any other function, but because it is used to make new objects, let's call this function a Maker Function.

If you are using friGame and following the conventions described in this post, instead of writing the Maker Function yourself, you can generate it like this:

var Rect = friGame.Maker(PRect);

As you can see this prototypal object model is not that much different compared to the class-based one, the only difference is that instead of creating a class you create a Prototype Object, and instead of creating the class instance and object initialization in 1 step, it is done in 2 steps, or by using a Maker function.

A final note before ending this post:

The Object.create function is relatively new, so older browsers like Internet Explorer 8 require a polyfill in order to work (friGame already implements it, so you don't have to worry about browser compatibility or polyfills).

In the next blog post we will see how a derived class is implemented in a prototypal object system, stay tuned.

Comments !