Search code examples
ecmascript-6es6-proxy

ES2015 Proxy: Assert that proxy is the same as target object


Is there an easy way to assert that an object is the target object of a proxy?

const o = {};
const p = new Proxy(o, {});

Equality operators do not seem to work, as outlined in this paper on page 6:

o == p; // false
o === p; // false
const q = new Proxy(o, {});
p === q; // false

Is there any way to verify that they refer to the same object, other then stringifying and reparsing the object?

Exemplary use-case:

I want to compare a proxied node with a non proxied one. Since I create the proxy myself, I know what behavior is to be expected.

const nodeList = new Proxy(document.querySelectorAll('div'), {
  get(target, key) { return new Proxy(target[key], {}); }
});

const specificNode = document.querySelector('div[data-target]');

for (const node of nodeList) {
  if (node === specificNode) { doSomethingElse(); } // Never happens, even if specificNode is in the nodeList
}

Solution

  • When you are creating the proxy yourself, you can also make it comparable. For example give a way to identify its target:

    const associatedTarget = Symbol();
    const p = new Proxy(target[key], {});
    p[associatedTarget] = target[key];
    return p;
    
    …
    if (node[associatedTarget] === specificNode)
    

    A better idea might be to give each target a singleton proxy, so that you can get the proxy for the specific node and compare it by ===:

    const proxies = new WeakMap();
    function makeUniqueProxy(t) {
      if (!proxies.has(t))
        proxies.set(t, new Proxy(t, {}));
      return proxies.get(t);
    }
    
    const nodeList = new Proxy(document.querySelectorAll('div'), {
      get(target, key) { return makeUniqueProxy(target[key]); }
    });
    
    const specificNode = makeUniqueProxy(document.querySelector('div[data-target]'));
    //                   ^^^^^^^^^^^^^^^
    
    for (const node of nodeList) {
      if (node === specificNode) { doSomethingElse(); } // just works
    }
    

    This approach also has the very desirable property that nodeList[0] === nodeList[0].