01. Iterable

В JavaScript добавлена новая концепция “итерируемых” (iterable) объектов:

  • Итерируемый объект (Iterable) - это объект или структура данных, чьи элементы должны быть доступны для последовательного перебора. Сама структура данных не обязательно должна быть линейной, но во время итерации элементы из неё извлекаются в последовательном порядке. Итерируемый объект содержит метод, доступный по символу Symbol.iterator. Этот метод является фабрикой для объектов-итераторов.

  • Итератор (Iterator) - объект, реализующий специальный протокол, для обхода элементов в структуре данных. Итераторы используются в тех местах, где нужно передать последовательность данных дальше по назначению -for-of, spread.

Следующие объекты являются итерируемыми:

  • arguments

  • Array

  • String

  • Set

  • Map

  • DOM структуры

  • Пользовательские объекты, имеющие символ-итератор.

В следующих операциях используется итератор:

  • Деструкция на основе паттерна массива

  • for-of цикл

  • Array.from

  • Spread (...)

  • Constructors of Maps and Sets

  • Promise.all(), Promise.race()

  • yield*

На основе итераторов работает множество языковых конструкций, добавленных в ES6:

// Array destruction
const [a,b] = new Set(['a', 'b', 'c']);

// for-of loop
for (const x of ['a', 'b', 'c']) {
      console.log(x);
}

// Array.from
const arr = Array.from(new Set(['a', 'b', 'c']));

// spread
const arr = [...new Set(['a', 'b', 'c'])];

// Конструкторы `Set` и `Map`
const map = new Map([[false, 'no'], [true, 'yes']]);
const set = new Set(['a', 'b', 'c']);

// Constructors of Sets and Maps receive iterables:
new Set("123").has("2")                                 // true
new WeakSet(function*() {
    yield {};
    yield myObj;
    yield {};
}()).has(myObj); // true

// Promice.all and Promice.race
Promise.all(iterableOverPromises).then(···);
Promise.race(iterableOverPromises).then(···);

// yield*
yield* anIterable;

Особенности итератора:

  • Является ли объект итерируемым зависит от наличия на нем метода с ключом Symbol.iterator, который возвращает валидный итератор.

  • Обычные объекты не являются итерируемыми.

  • В отличие от массивов, “перебираемые” объекты могут не иметь “длины” length.

  • Возможны и бесконечные итераторы. Нет никаких ограничений на next, он может возвращать всё новые и новые значения, и это нормально.

  • Оператор spread автоматически превращает итерируемый объект в массив: Math.max(...range);

  • Если сам объект реализует протокол итератора, тогда и вызов функции-итератора должен просто возвращать this.

  • Является ли итератор закрываемым?

  • Генераторы являются закрываемыми по умолчанию.

  • Не все итераторы сами являются итерируемыми. То есть не на всех итераторах определен Symbol.iterator возвращающий this.

Last updated