我想创建一个包装器机制:我们包装c
,以便新的新对象w
拥有自己的属性和方法,但是c
也可以访问。
// Note: this class might be from an external lib
class C {
f() {
console.log('f (original)');
this.p = 'p';
}
}
class W {
f() {
console.log('f (new)');
super.f(); // TypeError: (intermediate value).f is not a function
console.log(this.p);
}
}
// Note: this value is external for us
const c = new C();
const w = Object.create(null, Object.getOwnPropertyDescriptors(W.prototype));
Object.setPrototypeOf(w, c);
w.f(); // expected:
// f (new)
// f (original)
// p
我这样做是否正确?
为什么会发生错误?
更新:P.S.我确实知道我可以使用合成,但是我想了解错误的来源。
答案 0 :(得分:1)
为什么会发生错误?
因为使用W.prototype.f
的{{1}}方法只关心super
的原型来评估W.prototype
所引用的内容。 super
关键字本质上是静态查找,具体取决于声明该方法的对象,而忽略了调用该方法的对象的原型链。
如果我们translate去
super
我们可以看到class W {
f() {
console.log('f (new)');
Object.getPrototypeOf(W.prototype).f.call(this); // TypeError: (intermediate value).f is not a function
console.log(this.p);
}
}
不是函数……
因此,您可以通过执行Object.prototype.f
而不是Object.setPrototypeOf(W.prototype, C.prototype)
(或Object.setPrototypeOf(w, c)
)来解决此问题,但我不建议这样做。如果您确实想影响所有实例,那么您已经编写了w = Object.create(c, …)
(与使用class W extends C
的结果相同)。
答案 1 :(得分:0)
例如,您要使用extends
关键字:
class C {
f() { console.log( "C.f" ); }
}
class W extends C {
f() {
super.f()
console.log( "W.f" );
}
}
const w = new W();
w.f(); // will output C.f W.f