Reputation: 3696
I have the following proxy handler that logs get events.
const proxyHandler = {
get: function(target, prop) {
console.log("get", prop);
return Reflect.get(target, prop);
}
};
const obj = new Proxy(
{
value: 4,
text: "hi",
get textVal() {
return this.text.repeat(this.value);
},
getTextVal() {
return this.text.repeat(this.value);
}
},
proxyHandler
);
console.log("------- normal func -------")
console.log(obj.getTextVal());
console.log("------- getter func -------")
console.log(obj.textVal);
When I log console.log(obj.getTextVal())
I get:
get getTextVal
get text
get value
hihihihi
But when I log the getter console.log(obj.textVal)
, I only get the following:
get textVal
hihihihi
How can I make obj.textVal
log the get text
and get get value
events using proxy? ie. When running console.log(obj.textVal)
I would like the following result.
get getTextVal
get text
get value
hihihihi
Upvotes: 1
Views: 85
Reputation: 231
The above answer works but there is a bit more elegant solution. You are missing the receiver
in your Proxy trap and Reflect arguments. Simply change the Proxy to this:
const proxyHandler = {
get: function(target, prop, receiver) {
console.log("get", prop);
return Reflect.get(target, prop, receiver);
}
};
Notice the new
receiver
in the trap and Reflect arguments.
There is an important distinction between a Proxy trap target
and receiver
. In this case, the target
is the underlying raw object while the receiver
is the Proxy wrapper. If you do not pass the receiver
to the Reflect call everything inside the get
operation will be run against the raw object and won't trigger the Proxy traps.
If you have the time I suggest you read the relevant parts of the ES6 spec to fully grasp the difference between these two. Otherwise, just make sure that you forward all Proxy trap args to the matching Reflect call if you are aiming for a transparent wrap.
Upvotes: 2
Reputation: 10808
You can set the Proxy
instance to proxyHandler
object and access the properties through it (instead of this
).
const proxyHandler = {
get: function(target, prop) {
console.log("get", prop);
return Reflect.get(target, prop);
}
};
const proxifiedObj = {
value: 4,
text: "hi",
get textVal() {
return this.proxyInstance.text.repeat(this.proxyInstance.value);
},
getTextVal() {
return this.text.repeat(this.value);
}
}
obj = proxifiedObj.proxyInstance = new Proxy(proxifiedObj, proxyHandler);
console.log("------- normal func -------")
console.log(obj.getTextVal());
console.log("------- getter func -------")
console.log(obj.textVal);
console.log(obj.textVal);
get getTextVal
get text
get value
hihihihi
Update:
Or you could do the same thing by creating a custom Proxy
that does the assignment for you
(Note: Proxy
class cannot be extended but we can use the constructor return value pattern):
class InstanceAwareProxy {
constructor(proxifiedObject, proxyHandler) {
return proxifiedObject.proxyInstance
= new Proxy(proxifiedObject, proxyHandler);
}
}
obj = new InstanceAwareProxy(proxifiedObj, proxyHandler);
Upvotes: 1