Ітератор - об'єкт з методом next(), який щоразу повертає { value, done }. Ітерований об'єкт має метод [Symbol.iterator](), що повертає ітератор.
Саме на цьому протоколі працюють for...of, spread ([...x]), деструктуризація, Array.from, Promise.all, конструктори Map і Set. Масиви, рядки, Map, Set, NodeList - ітеровані з коробки; звичайні об'єкти - ні.
Власний ітерований об'єкт найпростіше зробити генератором:
class Range {
constructor(from, to) {
this.from = from;
this.to = to;
}
*[Symbol.iterator]() {
for (let i = this.from; i <= this.to; i++) {
yield i;
}
}
}
[...new Range(1, 5)]; // [1, 2, 3, 4, 5]
for (const n of new Range(1, 3)) console.log(n);
Навіщо це на практиці:
- Ліниві послідовності: значення обчислюються лише тоді, коли їх просять. Можна описати навіть нескінченну послідовність і взяти з неї 10 елементів.
- Однаковий інтерфейс для власних колекцій - їх можна передавати скрізь, де очікується ітероване.
- Асинхронні ітератори (
Symbol.asyncIterator,for await...of) - для потоків даних: сторінки API, рядки великого файлу, потік відповідіfetch.
Нові «ітераторні хелпери» (Iterator.prototype.map, filter, take, drop) дозволяють працювати з ітераторами ліниво, не перетворюючи їх на масив. Вони вже є в сучасних браузерах і Node.js 22+.