为什么设置与代理不兼容? [英] Why is Set Incompatible with Proxy?

查看:84
本文介绍了为什么设置与代理不兼容?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

JavaScript Set 似乎完全不兼容使用JavaScript 代理,尝试代理() a Set()

JavaScript Set appears to be entirely incompatible with JavaScript proxies, attempting to Proxy() a 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

In事实上,代理一个 Set()以任何方式断断续续 - 即使我们的代理处理程序什么都不做!比较 p =新代理({},{}) vs p =新代理(新Set(),{})。 (这适用于Firefox(52.0.2)和Chromium(57.0.2987.133)。)

In fact, proxying a Set() in any way breaks it categorically - even if our proxy handler does nothing at all! Compare p = new Proxy({}, {}) vs p = new Proxy(new Set(), {}). (This applies both in Firefox (52.0.2) and Chromium (57.0.2987.133).)

我似乎找不到可信的参考或文档,为什么JavaScript 代理一个设置对象,为什么它会遇到VM错误?

I can't seem to find a credible reference or documentation for this, why cannot JavaScript Proxy a Set object and why is it hitting a VM Error?

推荐答案


我正在尝试代理() a Set()

但是,你没有使用任何可用的陷阱 - 有没有添加一个。您可以在通话 p.add(55)中拦截的所有内容是属性访问 .add ,它通过获取陷阱并返回一个函数。

However, you haven't used any of the available traps - there is no add one. All that you can intercept in the call p.add(55) is the property access to .add on the proxy, which goes through the get trap and returns a function.

如果你想要拦截对 add 方法的调用,根本不需要代理,更好(子类和)覆盖该方法类似于 .set 被覆盖此处此处 地图

If you want to intercept calls to the add method, you don't need a proxy at all, better (subclass and) overwrite that method similar to how .set was overridden here and here for Map.


代理 Set()以任何方式断断续续地

proxying a Set() in any way breaks it categorically

是的,因为代理不再是 Set

Yes, because the proxy is not a Set any more.

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的对象上调用设置方法会引发异常(例如可用于检测它们)。有关具体情况,请参阅 ECMAScript6§23.2.3.1

Calling Set methods on objects that are no True Sets does throw an exception (which e.g. can be used for detecting them). For your particular case, see ECMAScript 6 §23.2.3.1:


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

"If S does not have a [[SetData]] internal slot, throw a TypeError exception."

事实上, p 是一个代理(确实有内部代理方法和插槽,尤其是 [[ProxyHandler]] [[ProxyTarget]] )而不是像 s 及其 [[SetData]] 内部广告位。

And indeed, p is a proxy (which does have the internal Proxy methods and slots, especially [[ProxyHandler]] and [[ProxyTarget]]) instead of a set like s with its [[SetData]] internal slot.

你理所当然地期待 如果尚未定义陷阱,则默认行为是将操作转发到目标,但这仅适用于属性访问等标准行为,而不适用于内部插槽异国情调的物品。

You reasonably were expecting that "if a trap has not been defined, the default behavior is to forward the operation to the target", however that only applies to standard behaviours like property access, and not the internal slots of exotic objects.

这篇关于为什么设置与代理不兼容?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆