Alex Rivera | Logout

Javascript inheritance - instanceof not working?

Asked 2010-06-30T00:17:12.330
16

I'm writing a simple platform game using javascript and html5. I'm using javascript in an OO manner. To get inheritance working i'm using the following;

// http://www.sitepoint.com/blogs/2006/01/17/javascript-inheritance/
function copyPrototype(descendant, parent) {
    var sConstructor = parent.toString();
    var aMatch = sConstructor.match(/\s*function (.*)\(/);
    if (aMatch != null) { descendant.prototype[aMatch[1]] = parent; }
    for (var m in parent.prototype) {
        descendant.prototype[m] = parent.prototype[m];
    }
};

For the sake of this post consider the following example;

function A() {
 this.Name = 'Class A'
}
A.prototype.PrintName = function () {
 alert(this.Name);
}

function B() {
 this.A();
}
copyPrototype(B, A);

function C() {
 this.B();
}
copyPrototype(C, B);

var instC = new C();

if (instC instanceof A)
  alert ('horray!');

As I understand it I would expect to see a horray alert box, because C is an instance of C & B & A. Am I wrong? Or am I just using the wrong method to check? Or has copyPrototype knackered the instanceof operator?

Thanks as always for taking the time to read this!

Shaw.

Edit
Report

2 Answers

19

The problem is that the copyPrototype function only copies the properties from a constructors prototype to another one, for example, at the end, the intenal [[Prototype]] link of C.prototype simply points to Object.prototype.

The prototype chain of instC and constructor's prototypes look like this:

                [[Prototype]]
    A.prototype -------------->|-------------------|
                               |                   |
    B.prototype -------------->|  Object.prototype | ---> null
                               |                   |
    C.prototype -------------->|-------------------|
        ^
        |
      instC

The instanceof operator traverses the prototype chain, your instC object, as you can see, will have on its prototype chain only C.prototype and Object.prototype.

You can achieve what you want by setting your constructor's prototypes to be object instances of their "parent" constructors, for example:

function A() {
  this.Name = 'Class A'
}

A.prototype.PrintName = function () {
  alert(this.Name);
}

function B() {
  //..
}
B.prototype = new A();
B.prototype.constructor = B; // fix constructor property


function C() {
  //..
}

C.prototype = new B();
C.prototype.constructor = C; // fix constructor property

var instC = new C();
if (instC instanceof A)
  alert('horray!');

Now the prototype chain of the instC object looks like this:

           ---------------        ---------------        ---------------
 instC --> | C.prototype | -----> | B.prototype | -----> | A.prototype |
           ---------------        ---------------        ---------------
                                                                |
                                                                V
                   
answered 2010-06-30T00:30:39.510
1

Ok I've found a solution which keeps the instanceof function working, as well as allowing me to pass constructor parameters through the inheritance chain. The solution is detailed here; https://developer.mozilla.org/en/Core_JavaScript_1.5_Guide/Details_of_the_Object_Model - my class structure now looks like this;

function A(p) {
 this.Position = p || new Vector2d(0,0);
}

function B(p) {
 this.base = A;
 this.base(p);
}
B.prototype = new A;

function C(p) {
 this.base = B;
 this.base(p);
}
C.prototype = new B;

if(C instanceof A)
  alert (' it worked!! '); // you now see this alert box!

Thanks CMS for highlighting to me why this wasn't working!!

You can check out the full project (well an older build which, at time of writing has yet to see this new OO method put in the whole way through) up at http://8weekgame.shawson.co.uk/ - just check out my latest posts.

answered 2010-06-30T15:40:19.993

Your Answer