1

How can I Proxy a Map, and then access the values of the proxied map?

Here is the code I am attempting:

const things = new Proxy(new Map(), {
  set(t, k, v) {
    console.log(t, k, v);
    Reflect.set(t, k, v);
  }
});

things['foo'] = 'bar'
// console log: Map(0) {} "foo" "bar"

console.log(things['foo']);
// console log: "bar"

things.values()
Uncaught TypeError: Method Map.prototype.values called on incompatible receiver [object Object]
    at Proxy.values (native)
000
  • 26,951
  • 10
  • 71
  • 101

1 Answers1

1

So it seems that Map methods complain if its thisArg is not an actual Map object. One solution would be to add a get to the proxy that checks if the property being fetched is a function, and if so, it returns a function that calls the requested function using the original, non-Proxy object.

const things = new Proxy(new Map(), {
  set(t, k, v) {
    console.log(t, k, v);
    Reflect.set(t, k, v);
  },
  get(t, k) {
    if (typeof t[k] === "function") {
      return (...args) => Reflect.apply(t[k], t, args)
    }
    return t[k];
  }
});

One potential down-side to this is that the function returned will be effectively bound to the original map. Probably not an issue for most cases, but it will render calls like things.values.call(someOtherMap) useless. There are probably ways to work around this if it's an issue.

spanky
  • 2,768
  • 8
  • 9
  • Another downside is that the Map can no longer store functions as keys, which the native Map is able to do. – 000 Aug 15 '17 at 20:41
  • Actually it seems that is not a problem. `t[k]` accesses the map's prototype methods, and `t.get(k)` accesses the values by key. – 000 Aug 15 '17 at 20:43
  • It could be a problem if the values are functions that need to have their *thisArg* set to a specific value. – spanky Aug 15 '17 at 20:50
  • Although this has pitfalls for the general use, this solution does meet my specific needs. Accepting this answer. Thanks. – 000 Aug 15 '17 at 21:07