Перейти к основному содержимому

Итераторы

Итератор в JavaScript — объект, который позволяет обращаться к элементам коллекции по одному за раз, отслеживая своё текущее положение внутри последовательности.

Для того, чтобы объект был итерируемым, в нём должен быть реализован метод итератора, доступный через свойство [Symbol.iterator]. Этот метод не принимает аргументов и должен возвращать объект, соответствующий протоколу итератора.

Если объект является итерируемым, с ним можно использовать цикл for..of и оператор spread. Некоторые встроенные типы (Array, Map, Set и др.) являются итерируемыми.

Протокол итератора

Объект является итератором, если в нем определён метод next, реализующий следующую логику.

Метод возвращает объект с двумя свойствами: done и value.

  • done:
    • true, если итератор достиг конца, в этом случае свойство value может определять возвращаемое значение итератора
    • false, если итератор может генерировать следующее значение последовательности; отсутствие свойства эвквивалентно false
  • value: любое JavaScript значение, возвращаемое итератором; может быть опущено, если done имеет значение true

Опционально у итератора может быть метод return, который может принимать аргумент и использоваться для явного завершения итерации и возврата заданного значения. Данный метод должен возвращать объект с такой же логикой, как и метод next.

Пример

class MyRange implements Iterable<number>, Iterator<number> {
  public readonly from: number;
  public readonly to: number;
  private current: number;

  constructor(from: number, to: number) {
    this.from = from;
    this.to = to;
  }

  public [Symbol.iterator](): Iterator<number> {
    this.current = this.from;
    return this;
  }

  public next(): IteratorResult<number> {
    if (this.current <= this.to) {
      return {value: this.current++};
    } else {
      return {done: true};
    }
  }
}
const range = new MyRange(0, 4);
const values = [...range]; // [0, 1, 2, 3, 4]

for (const value of range) console.log(value);
// 0 1 2 3 4