将 base class 添加到现有原型链,以便 instanceof 工作

Add base class to existing prototype chain so that instanceof works

我有一个现有的原型层次结构,我想修改它以保持层次结构完整,但在它的末尾添加一个额外的原型。 instanceof 应该 return 对于所有原型都是正确的。

即:假设我有 B->A,我想将其设为 B->A->Base。现在 instanceof 对于 A、B、Base 应该 return 为真。

我尝试使用 B.prototype.prototype 和 Object.setPrototypeOf(),但两种情况都不成功。

样本 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

这表明从B到A的继承关系;

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

所以,鉴于此;

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!"); }
}

不引用 A,你需要这个;

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

这样;

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

怎么样?一起玩吧 here.

正如 Bergi 所提到的,要以与 class 扩展相同的方式完成 Object.setPrototypeOf(A,Base) 而无需引用 A,Object.setPrototypeOf(Object.getPrototypeOf(B.prototype.constructor), Base)。 (需要调查这个,报告它导致循环继承错误...)

扩展测试 here 以执行 class 构造函数继承,如上所示。适用于 Chrome 53 (V8 5.3.332.45)。

编辑:注意,这是猴子修补继承链。这对性能来说不是一个好主意。