1

I have created a simple Proxy example on a Map Object. I can't figure out why the Set handler is not being executed and Get is executed instead, for Sets.

const handler = {
  get: (targetObj, propName, receiverProxy) => {
    console.log('PROXY: From get.')
    let ret = Reflect.get(targetObj, propName, receiverProxy)
    if (typeof ret === 'function') {
      ret = ret.bind(targetObj)
    }
    return ret
  },
  set: (targetObj, propName, propValue, receiverProxy) => {
    console.log('PROXY: From set.')
    return Reflect.set(targetObj, propName, propValue, receiverProxy)
  },
}

const targetMap = new Map([
  ['iron', 'man'],
])
const targetObj = {}
const proxy = new Proxy(targetMap, handler)
console.log(proxy.set('super', 'man'))
console.log(proxy.get('super'))
Cazineer
  • 2,235
  • 4
  • 26
  • 44
  • It executes your `get()` because the proxy will be involved in accessing the "set" property of the target object (the Map instance). The `set()` and `get()` methods of the handler are about property access and update; they have nothing to do with the methods on the Map prototype. You'll see your `set()` called if you tried `proxy.x = 1;` or something. – Pointy Apr 10 '18 at 19:57
  • Where did you find that code? It looks like an exact copy from the answer to the duplicate :-) – Bergi Apr 10 '18 at 20:06
  • I believe it came from that post. The thing is, the code in that answer appears to work and mine does not, even though mine is nearly identical. – Cazineer Apr 10 '18 at 20:08
  • @Kainan The first paragraph of that answer explains why it doesn't work. And the code in the first snippet there is not claimed to work, it only does intercept *property accesses* and nothing else. For how to intercept `.set()` and `.get()` calls, see the second part of the answer. – Bergi Apr 10 '18 at 20:11

2 Answers2

1

If you want a proxy setup that lets you intercept attempted calls to the Map .set() method, you'd have to do something like this:

let handler = {
  get: (target, property, proxy) {
    if (property === "set") {
      console.log("intercepted a '.set' access on the proxied map");
      return (key, value) => {
        console.log("intercepted a 'set()' call on the proxied map");
        return target.set(key, value);
      };
    }
    return target[property];
  }
};

The "get" handler method is called for any property access is attempted. In the method call

proxy.set("some key", "some value");

the "set" property of the object has to be looked up before the method can actually be called. It's that lookup operation that results in the handler "get" method invocation.

Now if you make the proxy as in your code and then do

proxy.set("some key", "some value");

you'll see that the log message fires when that "interceptor" function you returned is invoked.

Bergi
  • 630,263
  • 148
  • 957
  • 1,375
Pointy
  • 405,095
  • 59
  • 585
  • 614
0

Set and get doesn't work like that.

You can use the proxy object like any normal object. For example:

proxy.super = 'man';     // fires the setter
const x = proxy.super;   // fires the getter

Then, in your get/set handlers you can call the original get/set methods on the targetObj.

zord
  • 4,538
  • 2
  • 25
  • 30