I use a proxy to monitor all property accesses on a class's instances, like in the following example:
class Person {
public ageNow: number;
public constructor(ageNow: number) {
this.ageNow = ageNow;
const proxy = new Proxy(this, {
get: (target, property) => {
console.log(property);
return target[property as keyof typeof target];
},
});
return proxy;
}
public ageIn10Years1() {return this.ageNow 10;}
public get ageIn10Years2() {return this.ageNow 10;}
}
Now when I do e.g.
const peter = new Person(18);
console.log(peter.ageIn10Years1());
it prints 'ageInYears1'
, 'ageNow'
and 28
(in that order), as I expect.
However, when I do
console.log(peter.ageIn10Years2);
i.e. use a getter, it also prints 'ageInYears2'
and 28
but no longer 'ageNow'
, although that property is clearly accessed.
Why is that and how can I fix it?
CodePudding user response:
The getter use the original object not the proxy that you created
One solution is to call the getter function on the proxy.
class Person {
public ageNow: number;
public constructor(ageNow: number) {
this.ageNow = ageNow;
const proxy = new Proxy(this, {
get: (target, property) => {
const descriptor = Object.getOwnPropertyDescriptor(Person.prototype, property);
if (descriptor && typeof descriptor.get === 'function') {
console.log("calling",property);
return descriptor.get.call(proxy);
} else {
console.log(property);
return target[property as keyof typeof target];
}
},
});
return proxy;
}
public ageIn10Years1() {return this.ageNow 10;}
public get ageIn10Years2() {return this.ageNow 10;}
}
const peter = new Person(18);
console.log(peter.ageIn10Years1());
console.log(peter.ageIn10Years2);
CodePudding user response:
The problem is linked to how this
works.
In the first case you're calling your method like this:
peter.ageIn10Years1()
so this
is equal to peter
, meaning the proxy. That's why every value is correctly proxified.
You can verify that that binding your ageIn10Year1
method:
class Person {
constructor(ageNow) {
this.ageNow = ageNow;
this.ageIn10Years1 = this.ageIn10Years1.bind(this);
const proxy = new Proxy(this, {
get(target, property, receiver) {
console.log(property)
return target[property];
},
});
return proxy;
}
ageIn10Years1() {
return this.ageNow 10;
}
getAgeIn10Years2() {
return this.ageNow 10;
}
}
const peter = new Person(18);
console.log(peter.ageIn10Years1());
Now, this call work the same as the other.
In the second case, you're using a getter so this is not dynamically bounded and represent the initial object.
Maybe the simplest way to solve this problem would be to avoid using getters.