Javascript Jems - Prototype Inheritance
Written by Ian Elliot   
Monday, 18 October 2010
Article Index
Javascript Jems - Prototype Inheritance
Dynamic inheritance
Prototype chains

 

Banner

Dynamic inheritance

As Javascript is a dynamic language we do have to look a little at what happens if there are changes to the prototype object. If you have followed how everything works none of this should be surprising You can use it as a test to make sure you know how things work.

In a class based language if you change the code in a class then any classes that inherit from it also change their code in the same way - but of course only when the program is recompiled. In a Javascript program you have the opportunity to change a base class at runtime and see what happens.

First what happens if you change the prototype objects constructor? For example, assuming the definition of Point3D given earlier i.e.

Point3D.prototype=new Point2D();

then changing the constructor's properties or methods e.g.

var point=new Point3D();
Point2D.x=1;
alert(point.x);

has no effect i.e. point.x is still 0.

The reason is simply, and it should be obvious, that the prototype object is set to a new instance of an object constructed by Point2D which then has nothing to do with Point2D. In fact changing Point2D.x doesn't even change this.x in the constructor but adds a new x property to the function object. Note: if you are happy with the idea that the constructor really does act as an object factory and nothing much more then it probably seems silly to even expect a change to the constructor to have any effect on objects it has created.

Slightly more sensible is a change to the prototype object. For example:

var point=new Point3D();
Point3D.prototype.x=3;
alert(point.x);

In this case x is set to 3 even though the change to the prototype happens after point has been constructed.

The reason of course is that when the alert is carried out point doesn't have an x property of its own and so the prototype object is used to supply a value. Now consider what happens in the following case:

var point=new Point3D();
point.x=4;
Point3D.prototype.x=3;
alert(point.x);

In this case we explicitly set point.x so creating a local x property. In this case the alert displays 4 because x exists locally and the prototype property isn't used.

The same arguments work if the property is a method i.e a function.

The rule is that changing the prototype object does propagate unless the inheriting object has already stored a value in the property or overridden the method when a local version has been created and the link with the prototype object has been broken.

Finally what happens if you try to change the object used for the prototype after an object has inherited from it?

For example, suppose we also have a Point1D constructor:

function Point1D()
{
this.x=0;
}

If you were to base a Point3D on this instead of using Point2D there would be no y property inherited. That is

function Point3D()
{
this.z=0;
}
Point3D.prototype=new Point1D();

creates a Point3D object with no y property. Now if we go back to the original version:

function Point3D()
{
this.z=0;
}
Point3D.prototype=new Point2D();

and create an instance

var point=new Point3D();

then point has a y property via the prototype.

Now what happens if we change the prototype to Point2D?

Point3D.prototype=new Point2D();

Now any new Point3D objects created lack a y property via the prototype mechanism but what about objects already created like point?

The answer is that point still has a y property. The reason is that the current prototype object  is stored in an internal and hidden variable __proto__ when an object is constructed using the new operator.

This is the third and final "side effect" of using new.

The __proto__ property

A this point you might be starting to think of ways that you can add the prototype mechanism to object factories or ways of manipulating the mechanism to change and objects prototype.

You can't, for reasons introduced in the last section.

Javascript could have implemented the prototype mechanism by examining an objects constructor property to discover its constructor and then use the constructor's prototype property to retrieve the prototype object - but it doesn't.

When you create an object using new the internal property __proto__ is set to a reference to the current prototype object. This means that once created you can't change the prototype object of an instance.

You can change th prototype object used by the constructor but this only changes objects created in the future - existing objects are not changed.

What this means is that once created an object has a fixed prototype for all time.

This is the reason that the instanceof operator isn't affected by any changes you make to the constructor property or the constructors prototype property. The instanceof operator uses the __proto_ internal variable to discover the constructor that was used at the time the object was created. This means that an object cannot change its type if you use instanceof as an indicator of type.

<ASIN:059680279X>

<ASIN:1430230541>



Last Updated ( Monday, 18 October 2010 )