为什么设置与代理不兼容?

时间:2017-05-12 01:27:32

标签: javascript proxy

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错误?

1 个答案:

答案 0 :(得分:6)

  

我正在尝试Proxy() Set()

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

如果您想拦截对add方法的调用,您根本不需要代理,更好(子类和)覆盖该方法类似于覆盖.set的方式{{ 3}}和here 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 Sets的对象上调用Set方法会抛出异常(例如here)。对于您的具体情况,请参阅can be used for detecting them

  

&#34; 如果S没有[[SetData]]内部广告位,请抛出TypeError例外。&#34;

事实上,p是一个代理(确实有ECMAScript 6 §23.2.3.1,特别是[[ProxyHandler]][[ProxyTarget]]),而不是像s这样的集合[[SetData]]内部广告位。

你有理由期待&#34; 如果没有定义陷阱,默认行为是将操作转发到目标&#34;但是这只适用于标准行为喜欢属性访问,而不是异国情调对象的内部插槽。