1

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 
user3840170
  • 26,597
  • 4
  • 30
  • 62
Ryan King
  • 3,538
  • 12
  • 48
  • 72

2 Answers2

2

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.

Bertalan Miklos
  • 231
  • 1
  • 3
1

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);
Marinos An
  • 9,481
  • 6
  • 63
  • 96