Iterator() 构造函数

实验性: 这是一个 实验性技术
在生产环境中使用它之前,请仔细查看 浏览器兼容性表

Iterator() 构造函数旨在用作创建迭代器的其他类的 超类。当它本身被构造时,它会抛出错误。

语法

js
new Iterator()

注意: Iterator() 只能用 new 构造。尝试在没有 new 的情况下调用它会抛出一个 TypeError。此外,Iterator() 本身实际上不能被构造——它通常通过子类构造函数中的 super() 调用隐式地构造。

参数

无。

返回值

一个新的 Iterator 对象。

异常

TypeError

new.target 本身是 Iterator 函数时,即当 Iterator 构造函数本身被构造时。

描述

Iterator 代表一个抽象类——一个为其子类提供通用实用程序的类,但它本身并不打算被实例化。它是所有其他迭代器类的超类,用于创建实现特定迭代算法的子类——即,Iterator 的所有子类都必须实现 next() 方法,如 迭代器协议 所要求的那样。由于 Iterator 实际上没有提供 next() 方法,因此直接构造一个 Iterator 没有任何意义。

您还可以使用 Iterator.from() 从现有的可迭代或迭代器对象创建一个 Iterator 实例。

示例

子类化迭代器

以下示例定义了一个自定义数据结构 Range,它允许迭代。使对象可迭代的最简单方法是在对象中提供一个 [Symbol.iterator]() 方法,该方法采用生成器函数的形式。

js
class Range {
  #start;
  #end;
  #step;

  constructor(start, end, step = 1) {
    this.#start = start;
    this.#end = end;
    this.#step = step;
  }

  *[Symbol.iterator]() {
    for (let value = this.#start; value <= this.#end; value += this.#step) {
      yield value;
    }
  }
}

const range = new Range(1, 5);
for (const num of range) {
  console.log(num);
}

这可以工作,但它不像内置迭代器那样好。有两个问题

  • 返回的迭代器继承自 Generator,这意味着对 Generator.prototype 的修改将影响返回的迭代器,这会导致抽象泄漏。
  • 返回的迭代器没有从自定义原型继承,如果我们打算向迭代器添加额外方法,这会变得更加困难。

我们可以通过子类化 Iterator 来模仿内置迭代器(如 map 迭代器)的实现。这使我们能够定义额外的属性(如 [Symbol.toStringTag]),同时在返回的迭代器上提供迭代器帮助器方法。

js
class Range {
  #start;
  #end;
  #step;

  constructor(start, end, step = 1) {
    this.#start = start;
    this.#end = end;
    this.#step = step;
  }

  static #RangeIterator = class extends Iterator {
    #cur;
    #s;
    #e;
    constructor(range) {
      super();
      this.#cur = range.#start;
      this.#s = range.#step;
      this.#e = range.#end;
    }
    static {
      Object.defineProperty(this.prototype, Symbol.toStringTag, {
        value: "Range Iterator",
        configurable: true,
        enumerable: false,
        writable: false,
      });

      // Avoid #RangeIterator from being accessible outside
      delete this.prototype.constructor;
    }
    next() {
      if (this.#cur > this.#e) {
        return { value: undefined, done: true };
      }
      const res = { value: this.#cur, done: false };
      this.#cur += this.#s;
      return res;
    }
  };

  [Symbol.iterator]() {
    return new Range.#RangeIterator(this);
  }
}

const range = new Range(1, 5);
for (const num of range) {
  console.log(num);
}

如果您想创建许多自定义迭代器,子类化模式很有用。如果您有一个现有的可迭代或迭代器对象,它没有从 Iterator 继承,并且您只想在其上调用迭代器帮助器方法,您可以使用 Iterator.from() 来创建一个一次性的 Iterator 实例。

规范

规范
迭代器帮助器
# sec-iterator-constructor

浏览器兼容性

BCD 表格仅在浏览器中加载

参见