Javascript V8:ES6代理不';针对自定义对象时是否支持迭代协议?
我正在使用V8 API创建JavaScript对象。其中一些对象通过在Javascript V8:ES6代理不';针对自定义对象时是否支持迭代协议?,javascript,proxy,ecmascript-6,v8,Javascript,Proxy,Ecmascript 6,V8,我正在使用V8 API创建JavaScript对象。其中一些对象通过在Symbol.iterator属性处设置本机(拦截)函数来支持迭代 通过迭代这样一个对象非常有效。但是,如果我将其包装在一个空代理中(例如,let x=new proxy(obj,{});),则生成的对象是不可编辑的,如果试图对其进行迭代,就会抛出一个带有消息“非法调用”的TypeError 包装标准阵列不会出现此问题。这是一个V8错误吗 包装标准阵列不会出现此问题 是的,就是这样工作的。他们不关心他们正在迭代的对象的类型-他
Symbol.iterator
属性处设置本机(拦截)函数来支持迭代
通过迭代这样一个对象非常有效。但是,如果我将其包装在一个空代理中(例如,let x=new proxy(obj,{});
),则生成的对象是不可编辑的,如果试图对其进行迭代,就会抛出一个带有消息“非法调用”的TypeError
包装标准阵列不会出现此问题。这是一个V8错误吗
包装标准阵列不会出现此问题
是的,就是这样工作的。他们不关心他们正在迭代的对象的类型-他们只是访问它的.length
和索引属性(通常通过代理路由)
然而,其他标准的异国情调对象也没有表现得那么好。如果您试图调用[Symbol.迭代器]()
在一个或封装在代理中的对象上,它们会抱怨在错误的对象上被调用
这是一个V8错误吗
不,这是应用程序中的一个bug。您有三个选择:
- 创建一个迭代器,该迭代器不依赖于自定义对象的内部插槽,而是使用它们的公共(代理可拦截)属性接口。确保您的
方法没有对其接收器进行类型检查[Symbol.iterator]
- 检查迭代器方法中的接收器类型,如果它是代理(即具有
内部插槽),则使用该值。我强烈建议不要这样做,因为它不符合标准行为,并且在绕过处理程序时违反了代理[[ProxyTarget]]]
- 不要使用空代理:
let x = new Proxy(obj, { get(target, key, receiver) { if (key === Symbol.iterator) return target[Symbol.iterator].bind(target); else return Reflect.get(target, key, receiver); } });
[Symbol.iterator]
方法要求其持有者具有某些私有字段,当持有者是代理时,这些字段是不可访问的。快速跟进问题:您知道为什么proxy[Symbol.iterator]()
在不调用我的拦截器的情况下抛出异常,而it=proxy[Symbol.iterator];它()
调用拦截器并按预期崩溃?如果这是您所说的“拦截器”的意思,那么这两者都应该调用get
处理程序?我无法想象为什么不会。对不起,让我试着澄清一下。我没有指定自定义get
处理程序;该方法作为普通属性存储在目标上,并且在这两种情况下都可以正确检索。我不明白的是,为什么第一个语法在不调用方法的情况下抛出异常,而第二个语法调用方法并按预期崩溃。方法本身是一个本机函数,其调用会导致回调到本机(C++)代码中,但这与AICT无关。明显的区别是接收者(proxy
vsundefined
),这是js函数中的this
关键字的值,但我不知道本机函数是如何受到影响的。显然,有一些防护措施阻止您的自定义函数运行,但我不知道V8的详细信息。它也发生在非代理对象上吗;这种差异似乎存在于V8的函数调用机制中。如果x
是本机函数而y
是代理函数,则调用(y)会提前失败。