【问题标题】:Why is Set Incompatible with Proxy?为什么设置与代理不兼容?
【发布时间】:2017-10-11 04:41:06
【问题描述】:

JavaScript Set 似乎与 JavaScript proxies 完全不兼容,试图将 Proxy() Set()

var p = new Proxy(new Set(), {
  add(target, val, receiver) {
    console.log('in add: ', target, val, receiver)
  }
})
p.add(55)

导致 VMError:

Uncaught TypeError: Method Set.prototype.add called on incompatible receiver [object Object]
    at Proxy.add (native)
    at <anonymous>:1:3

事实上,代理Set() 绝对会破坏它——即使我们的代理处理程序根本不做任何事情!比较 p = new Proxy({}, {})p = new Proxy(new Set(), {})。 (这适用于 Firefox (52.0.2) 和 Chromium (57.0.2987.133)。)

我似乎找不到可靠的参考或文档,为什么 JavaScript Proxy 不能 Set 对象,为什么它会遇到 VM 错误?

【问题讨论】:

  • 代理中没有add 陷阱。看起来您正在寻找子类,而不是代理(它不是 Set 并且不能与 Set 方法一起使用)
  • @Bergi 你在哪里看到这个答案? Map 的答案不适用于 Set,也没有解释为什么空处理程序会破坏 Set 代理。至于缺乏陷阱:这是否记录在任何地方?为什么空陷阱{} 会导致 Set Proxy 出现 VMErrors?
  • 不,我不是在寻找子类,请在下次将其关闭之前阅读问题...
  • 解释确实适用,Maps 和 Sets 工作方式相同。实际上,它确实看起来您正在寻找拦截add 方法调用,子类是最简单的解决方案。
  • 我被问到 2 个问题,这些问题在我的问题中明确说明(在链接到“重复”问题的链接中都没有回答):ProxySet 不兼容?为什么即使在 empty handler 上也会导致 VMError?在我的问题中没有问“我如何拦截添加调用”。

标签: javascript proxy


【解决方案1】:

我正在尝试Proxy() Set()

但是,您没有使用任何available traps - 没有add 之一。您可以在调用p.add(55) 中拦截的所有内容是代理上对.add属性访问,它通过get 陷阱并返回一个函数。

如果您想拦截对add 方法的调用,则根本不需要代理,最好(子类和)覆盖该方法,类似于.set 被覆盖herehere 的方式Map.

以任何方式代理 Set() 都会断然破坏它

是的,因为代理不再是Set

var s = new Set([42]);
var p = new Proxy(s, {});
s.has(42) // true
console.log(s === p) // false
p.has.call(s, 42) // true
p.has(42) // exception - calls `has` on `p`, not on `s`

在没有 True Set 的对象上调用 Set 方法会引发异常(例如 can be used for detecting them)。对于您的特殊情况,请参阅ECMAScript 6 §23.2.3.1

如果S 没有[[SetData]] 内部槽,则抛出TypeError 异常。

确实,p 是一个代理(它确实有internal Proxy methods and slots,尤其是[[ProxyHandler]][[ProxyTarget]]),而不是像s 这样的集合,它的[[SetData]] 内部插槽。

您合理地期望“如果尚未定义陷阱,则默认行为是将操作转发到目标”,但这仅适用于属性访问等标准行为,而不适用于奇异物体的内部槽。

【讨论】:

  • 感谢您的全面回答。
猜你喜欢
  • 2013-06-27
  • 2013-10-21
  • 2017-10-08
  • 2014-11-06
  • 2017-02-07
  • 2012-01-26
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多