Reputation: 3529
I'm trying to create a (class) instance that copies the behavior of another class, but using itself as the state context (this). Normal functions work fine (like the setValue
function in the example below), but getters do not work. Here is a simple example:
const should = require('chai').should();
class One {
setValue(val) {
this._val = val;
}
get val() {
return this._val;
}
}
class Two {
constructor(one) {
this.one = one;
}
setValue(val) {
this.one.setValue.call(this, val);
}
get val() {
this.one.val.call(this);
}
}
let one = new One();
let two = new Two(one);
one.setValue(1);
two.setValue(2);
one.val.should.equal(1);
two.val.should.equal(2);
The above code explodes on the last line with the error:
TypeError: this.one.val.call is not a function
at Two.get val [as val] (C:\all\code\node-tests\invoke_getter.js:23:22)
at Object.<anonymous> (C:\all\code\node-tests\invoke_getter.js:32:5)
How can I make something like this work?
Upvotes: 4
Views: 1716
Reputation: 5703
Recall that property getters for class ends in its prototype
So to access the method, you may want to get it from its prototype:
const descriptor = Object.getOwnPropertyDescriptor(Object.getPrototypeOf(this.one), 'val')
Then you can call the getter on your two
instance:
class One {
setValue(val) {
this._val = val
}
get val() {
return this._val
}
}
class Two {
constructor(one) {
this.one = one
}
setValue(val) {
this.one.setValue.call(this, val)
}
get val () {
const desc = Object.getOwnPropertyDescriptor(Object.getPrototypeOf(this.one), 'val')
return desc.get.call(this)
}
}
const one = new One()
const two = new Two(one)
one.setValue(1)
console.log(two.val) // undefined (since _val does not exist on two yet)
two.setValue(2)
console.log(two.val) // 2
two._val = 3
console.log(two.val) // 3
Upvotes: 3