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

V8: ES6 proxies don't support iteration protocol when targeting custom objects?

我正在使用 V8 API 创建 JavaScript 对象。其中一些对象通过在 Symbol.iterator 属性.

处设置本机(拦截)函数来支持迭代

通过 for...of 迭代这样的对象非常有效。但是,如果我将它包装在一个空代理中(例如,let x = new Proxy(obj, {});),生成的对象是 not 可迭代的,并抛出一个 TypeError 和消息 [=23] =] 如果尝试对其进行迭代。

包装标准数组不会出现此问题。这是 V8 错误吗?

Wrapping a standard array doesn't exhibit this issue.

是的,这就是 array iterators 的工作方式。他们不关心他们正在迭代的对象的种类 - 他们只是访问其 .length 和索引属性(通常通过代理路由)。

然而,其他标准的奇异对象也表现不佳。如果您尝试在包装在代理中的 typed array, map or set 上调用 [Symbol​.iterator](),他们会抱怨在错误的对象上调用。

Is this a V8 bug?

不,这是应用程序中的错误。您有三个选择:

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