V8:ES6代理在定位自定义对象时不支持迭代协议?

Bit*_*tex 4 javascript proxy v8 ecmascript-6

我正在使用V8 API来创建JavaScript对象.其中一些对象通过在Symbol.iterator属性中设置本机(截获的)函数来支持迭代.

通过for...of完美的工作迭代这样的对象.但是,如果我将它包装在空代理(例如let x = new Proxy(obj, {});)中,则生成的对象不可迭代,TypeError如果尝试迭代它,则抛出带有"非法调用"的消息.

包装标准阵列不会出现此问题.这是V8的错误吗?

Ber*_*rgi 7

包装标准阵列不会出现此问题.

是的,这就是数组迭代器的工作方式.他们不关心他们迭代的对象的类型 - 他们只是访问它的.length索引属性(通过代理正常路由).

但是,其他标准的外来物体也不会表现得那么好.如果您尝试[Symbol​.iterator]()在包含在代理中的类型化数组,映射集合上调用,他们会对在错误的对象上调用而烦恼.

这是V8的错误吗?

不,这是应用程序中的一个错误.你有三个选择:

  • 创建一个不依赖于自定义对象的内部插槽的迭代器,而是使用它们的公共(代理可拦截)属性接口.确保您的[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);
        }
    });
    
    Run Code Online (Sandbox Code Playgroud)