JavaScript: aspects of the prototype object

In JavaScript, the prototype object is attached to every object on the page, either already existing or created from scratch. This object handles all the features related to objects, classes and, more broadly, inheritance. Since JavaScript is prototypical in its nature, it's almost impossible to work in a OO way without dealing with it. As you may have guessed, in JavaScript functions are actually first-class objects, so it's natural that every function that works as a class has its own prototype object. Strictly speaking, this object can also be considered as a property of every object, although not in the narrowest sense of the term.

The best way to understand this is simply one: testing! So let's test something by starting with a base class like this:

function Class() {

    this.property = 'Property';

}

alert(Class.prototype); // [object Object]

var myClass = new Class();

Now let's see what is our default setup:

alert(myClass.constructor); // function Class() {...}
alert(myClass.prototype); // undefined

As you can see, the constructor property of our class simply points to our function, while the prototype object of the instance is undefined. But we can actually use this property to extend our base class with a subclass, like so:

function SubClass() {

    this.say = function() {
    
        alert(this.property);
    
    }

}

Class.prototype = new SubClass();

var myClass = new Class();
myClass.say(); // 'Property'

Making the prototype object of our base class pointing to a new instance of our subclass, we actually extend our base class with the new method. But our prototype object (that of the instance) is still undefined:

alert(myClass.prototype); // undefined

The fact is that now prototype is not still associated with an object. Let's see another aspect:

function ClassB () {

    this.prop = 'Second property';

}

ClassB.prototype = {

    constructor: ClassB,
    method: function() {
    
        alert(this.prop);
    
    }

}

var myClassB = new ClassB();

alert(myClassB.constructor); // function ClassB() {...}
alert(myClassB.prototype); // undefined
alert(myClassB.constructor.prototype); // [object Object]
myClassB.method(); // 'Second property'

In this case, we've associated the prototype object with an object literal. Inside this object, we've properly set the constructor property to make it point to our class constructor. As you can see, the prototype object of the constructor is now associated with an object. Let's do a simple test:

ClassB.prototype.method.call(myClassB); // 'Second property'

This works because we're using the prototype object of the constructor, not of the instance. The instance is here used only to get the desired value by using call() on the newly created instance.

Leave a Reply

Note: Only a member of this blog may post a comment.