I want to create a wrapper mechanism: we wrap c
so new new object w
has own properties and methods but c
's are also accessible.
// 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
Do I do this in correct manner?
Why is error happen?
Update: P.S. I do understand that I could use composition but I want to understand the source of error.
Why does the error happen?
Because the W.prototype.f
method that uses super
only cares about the prototype of W.prototype
to evaluate what super
will refer to. The super
keyword is essentially a static lookup, depending on the object in which the method was declared, ignoring the prototype chain of the object that the method was called on.
If we translate to
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);
}
}
we can see that Object.prototype.f
is not a function…
So you could fix the issue by doing Object.setPrototypeOf(W.prototype, C.prototype)
instead of Object.setPrototypeOf(w, c)
(or w = Object.create(c, …)
), but I can't recommend that. If you really wanted to affect all instances, you'd have written class W extends C
already (which would have the same result as using Object.setPrototypeOf(W.prototype, C.prototype)
).