Search code examples
javascriptoopinheritanceinstanceof

Javascript inheritance - instanceof not working?


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.


Solution

  • These days you shouldn't need .prototype = new Thing(), I think I'm late to the party but you can just use Object.create on the prototype of the parent and then override the methods you're interested in overriding. An example:

    var IDataSource = function(){
        throw new Error("Not implemented, interface only");
    };
    
    IDataSource.prototype.getData = function(){
        throw new Error("Not implemented.");
    };
    
    var BasicDataSource = function(){};
    BasicDataSource.prototype = Object.create(IDataSource.prototype);
    BasicDataSource.prototype.getData = function(){
        //[do some stuff, get some real data, return it]
        return "bds data";
    };
    
    var MockDataSource = function(){};
    MockDataSource.prototype = Object.create(IDataSource.prototype);
    MockDataSource.prototype.getData = function(){
        //[DONT DO some stuff return mock json]
        return "mds data";
    };
    
    MockDataSource.prototype.getDataTwo = function(){
        //[DONT DO some stuff return mock json]
        return "mds data2";
    };
    
    
    var MockDataSource2 = function(){};
    MockDataSource2.prototype = Object.create(MockDataSource.prototype);
    
    
    
    
    var bds = new BasicDataSource();
    console.log("bds is NOT MockDataSource:", bds instanceof MockDataSource);
    console.log("bds is BasicDataSource:", bds instanceof BasicDataSource);
    console.log("bds is an IDataSource:", bds instanceof IDataSource);
    console.log("bds Data:", bds.getData());
    
    
    var mds = new MockDataSource();
    console.log("mds is MockDataSource:", mds instanceof MockDataSource);
    console.log("mds is NOT a BasicDataSource:", mds instanceof BasicDataSource);
    console.log("mds is an IDataSource:", mds instanceof IDataSource);
    console.log("mds Data:", mds.getData());
    console.log("mds Data2:",mds.getDataTwo());
    
    
    var mds2 = new MockDataSource2();
    console.log("mds2 is MockDataSource2:", mds2 instanceof MockDataSource2);
    console.log("mds2 is MockDataSource:", mds2 instanceof MockDataSource);
    console.log("mds2 is NOT a BasicDataSource:", mds2 instanceof BasicDataSource);
    console.log("mds2 is an IDataSource:", mds2 instanceof IDataSource);
    console.log("mds2 Data:", mds2.getData());
    console.log("mds2 Data2:",mds2.getDataTwo());
    

    If you run this code in node you will get:

    bds is NOT MockDataSource: false
    bds is BasicDataSource: true
    bds is an IDataSource: true
    bds Data: bds data
    mds is MockDataSource: true
    mds is NOT a BasicDataSource: false
    mds is an IDataSource: true
    mds Data: mds data
    mds Data2: mds data2
    mds2 is MockDataSource2: true
    mds2 is MockDataSource: true
    mds2 is NOT a BasicDataSource: false
    mds2 is an IDataSource: true
    mds2 Data: mds data
    mds2 Data2: mds data2
    

    No worry about parameters to constructors or any such craziness.