为什么 Set 与 Proxy 不兼容? [英] Why is Set Incompatible with Proxy?
问题描述
JavaScript Set 似乎与JavaScript 代理,试图代理()
一个 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:
results in a 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).)
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 Proxy
不能成为 Set
对象,为什么它会遇到 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?
推荐答案
我正在尝试
Proxy()
一个Set()
但是,您还没有使用任何 可用陷阱 - 没有 add
陷阱.您可以在调用 p.add(55)
中拦截的只是代理上对 .add
的属性访问,它通过get
捕获并返回一个函数.
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
在此处和此处被覆盖 用于 Map
.
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 的对象上调用 Set
方法确实会引发异常(例如 可以使用用于检测它们).对于您的特定情况,请参阅 ECMAScript 6 §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 aTypeError
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.
这篇关于为什么 Set 与 Proxy 不兼容?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!