MiB MiB - 2 months ago 8
Javascript Question

Add base class to existing prototype chain so that instanceof works

I have an existing prototype hierarchy and I want to modify it so that the hierarchy is kept intact but an additional prototype is added to then end of it.

instanceof
should return true for all prototypes.

I.e.: say I have B->A and I want to make it B->A->Base. Now
instanceof
should return true for A, B, Base.

I tried using B.prototype.prototype and Object.setPrototypeOf(), but no luck in either case.

Sample with Object.setPrototypeOf():

class A {
do() {
console.log("do A");
}
}


class B extends A {
do() {
console.log("do B");
}

doB() {
console.log("what");
}
}


var a = new A();
var b = new B();

a.do();
b.do();
b.doB();

console.log(a instanceof A) // true
console.log(a instanceof B) // false

console.log(b instanceof A) // true
console.log(b instanceof B) // true


class Base {
doBase() {
console.log("this is the base!");
}
}


// now add Base to B's chain, so that B -> A -> Base
// TODO: doesn't work!

Object.setPrototypeOf(Object.getPrototypeOf(Object.getPrototypeOf(B)), Base.prototype)
//Object.setPrototypeOf(Object.getPrototypeOf(B), Base)


console.log(Object.getPrototypeOf(B))
console.log(Object.getPrototypeOf(Object.getPrototypeOf(B)))


var c = new B();

console.log(c instanceof B) // true
console.log(c instanceof A) // true
console.log(c instanceof Base) // false (!!! how to fix it?)

c.doBase(); // crash, not a function

Answer

This shows inheritance relationship from B to A;

console.log(Object.getPrototypeOf(B.prototype) === A.prototype);

So, given this;

class A { do() { console.log("do A"); } }

class B extends A {
  do() { console.log("do B"); }
  doB() { console.log("what"); }
}

class Base {
  doBase() { console.log("this is the base!"); }
}

Without referencing A, You need this;

Object.setPrototypeOf(Object.getPrototypeOf(B.prototype), Base.prototype);

Such that;

console.log(new A() instanceof Base); // true
console.log(new B() instanceof Base); // true
(new B()).doBase(); // this is the base!

How's that? Play with it here.

As mentioned by Bergi, to accomplish Object.setPrototypeOf(A,Base) in the same manner as class extension without referencing A, Object.setPrototypeOf(Object.getPrototypeOf(B.prototype.constructor), Base).

Comments