【问题标题】:Add base class to existing prototype chain so that instanceof works将基类添加到现有原型链,以便 instanceof 工作
【发布时间】:2016-09-25 20:03:20
【问题描述】:

我有一个现有的原型层次结构,我想修改它以保持层次结构不变,但在其末尾添加了一个额外的原型。 instanceof 应该为所有原型返回 true。

即:假设我有 B->A,我想让它成为 B->A->Base。现在instanceof 应该为 A、B、Base 返回 true。

我尝试使用 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

【问题讨论】:

  • 这看起来很疯狂。你为什么想这么做?为什么不直接创建Base 的实例并使其成为B 的子类?这就是 OO 的意义所在。
  • "我想修改它以使层次结构保持不变" - 这是不可能的。 A原本继承自Object,现在应该继承自Base?这不是“完整的”。
  • 是的,确实很疯狂。而不是我的选择。我正在尝试修复一个较旧的框架,以便可以将它与 ES6 类一起使用。所述框架使用 Component 基类扩展所有用户组件,但这样做是通过覆盖原型然后将所有原始属性复制回其中来实现的。所以它现在看起来像是继承自 Component,从而失去了原来的类。然后我不能再实例化它了,因为 babel 生成了一个 _classCallCheck 现在失败了。
  • @Bergi:是的,完全正确。仅在之后应该是 Base 的最终对象之前保持完整。也许将其视为链中的插入,Object 仍然会在最后。
  • @MiB 其实我的意思是你应该暴露框架的Component 类,这样你就可以写class A extends myframework.Component 并且框架不需要再覆盖任何原型了

标签: javascript inheritance prototypal-inheritance


【解决方案1】:

这显示了从 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所说,以与类扩展相同的方式完成Object.setPrototypeOf(A,Base)而不引用A,Object.setPrototypeOf(Object.getPrototypeOf(B.prototype.constructor), Base)。 (这个需要调查,报告它导致循环继承错误...)

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

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

【讨论】:

  • 别忘了Object.setPrototypeOf(A, Base)
  • 我为什么要这样做?
  • 好主意!但我的问题正是我当时不了解 A。我得到的只是对 B 的引用,现在我必须找出 A,然后设置原型。
  • 哦,好的。没问题。
  • Object.getPrototypeOf(B)B.__proto__,与 B.prototype 不同。 stackoverflow.com/questions/9959727/…
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-07-21
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-01-12
相关资源
最近更新 更多