Add base class to existing prototype chain so that instanceof works

狂风中的少年 提交于 2019-12-23 21:16:24

问题


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

回答1:


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). (Need to investigate this, reported that it causes a cyclic inheritance error...)

Extended the test here to perform the class constructor inheritance as shown above. Works in Chrome 53 (V8 5.3.332.45).

Edit: Note, this is monkey-patching the inheritance chain. It's not a fantastic idea for performance.



来源:https://stackoverflow.com/questions/39691276/add-base-class-to-existing-prototype-chain-so-that-instanceof-works

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!