【问题标题】:ES2015 Proxy: Assert that proxy is the same as target objectES2015 代理:断言代理与目标对象相同
【发布时间】:2017-05-05 12:49:22
【问题描述】:

有没有一种简单的方法可以断言一个对象是代理的目标对象?

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

等式运算符似乎不起作用,as outlined in this paper on page 6

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

除了对对象进行字符串化和重新解析之外,还有什么方法可以验证它们是否引用了同一个对象?

示例用例:

我想将代理节点与非代理节点进行比较。由于我自己创建了代理,所以我知道预期的行为。

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
}

【问题讨论】:

  • 你为什么要关心?如果您不知道代理的作用,它的行为可能类似于 target 或绝对不是。
  • @Bergi 请参阅上面的示例用例。
  • 为什么不做if ("target" in node.dataset) … else?当然,创建没有任何陷阱的内部代理是毫无意义的。
  • 这只是一个非常简单的例子。现实世界的用例有代理陷阱,但对于这个 SO 问题来说可能太多了。

标签: ecmascript-6 es6-proxy


【解决方案1】:

当您自己创建代理时,您也可以使其具有可比性。例如给出一种识别其目标的方法:

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

…
if (node[associatedTarget] === specificNode)

一个更好的主意可能是给每个目标一个单例代理,这样您就可以获取特定节点的代理并通过===进行比较:

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
}

这种方法还具有nodeList[0] === nodeList[0] 非常理想的特性。

【讨论】:

  • 使用 Wea​​kMaps 跟踪代理是非常好的解决方案,谢谢。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-11-12
  • 2016-03-27
  • 2017-08-31
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多