Що таке ітератор?
Що таке ітератор
Ітератор - це об'єкт, який покроково перебирає (ітерує) елементи іншої структури даних - масиву, рядка, Set, Map тощо.
Він реалізує спеціальний інтерфейс - у нього є метод next(),
який повертає об'єкт вигляду:
{ value: <значення>, done: <логічний прапорець> }Приклад простого ітератора
const iterator = {
current: 1,
last: 3,
next() {
if (this.current <= this.last) {
return { value: this.current++, done: false };
} else {
return { done: true };
}
}
};
console.log(iterator.next()); // { value: 1, done: false }
console.log(iterator.next()); // { value: 2, done: false }
console.log(iterator.next()); // { value: 3, done: false }
console.log(iterator.next()); // { done: true }Ітератор сам зберігає свій стан і знає, де він "зупинився".
Що робить ітератор особливим
Ітератори - це універсальний спосіб перебору.
Наприклад, масиви, рядки, Map і Set вже вбудовано ітеровані -
у них є спеціальний символьний ключ Symbol.iterator.
Приклад вбудованого ітератора масиву
const arr = [10, 20, 30];
const iterator = arr[Symbol.iterator]();
console.log(iterator.next()); // { value: 10, done: false }
console.log(iterator.next()); // { value: 20, done: false }
console.log(iterator.next()); // { value: 30, done: false }
console.log(iterator.next()); // { value: undefined, done: true }Тобто for...of під капотом робить те саме.
for...of та ітератори
const arr = [1, 2, 3];
for (const value of arr) {
console.log(value);
}
// 1
// 2
// 3Цикл for...of автоматично викликає arr[Symbol.iterator]()
і перебирає значення, поки done: true.
Створення власного ітерованого об'єкта
Щоб зробити свій об'єкт "перебірним" (ітерованим),
у ньому потрібно визначити метод з ключем Symbol.iterator.
const range = {
from: 1,
to: 5,
[Symbol.iterator]() {
let current = this.from;
const last = this.to;
return {
next() {
if (current <= last) {
return { value: current++, done: false };
} else {
return { done: true };
}
}
};
}
};
for (const num of range) {
console.log(num); // 1 2 3 4 5
}Тепер range можна використовувати в for...of, Array.from(), ...spread та інших конструкціях.
Використання ітераторів в інших контекстах
| Конструкція | Що робить |
|---|---|
for...of | Перебирає ітеровані значення |
...spread | Розкриває ітератор |
Array.from(iterable) | Перетворює ітератор на масив |
Деструктуризація [a, b] = iterable | Витягує значення через ітератор |
Приклад:
const set = new Set(['a', 'b', 'c']);
const arr = [...set]; // ['a', 'b', 'c']Працює, тому що у Set є вбудований Symbol.iterator.
Асинхронні ітератори
З'явилися в ES2018:
асинхронні ітератори повертають проміси в next().
const asyncIterable = {
async *[Symbol.asyncIterator]() {
yield 'A';
yield 'B';
yield 'C';
}
};
for await (const value of asyncIterable) {
console.log(value);
}
// A
// B
// CЦе використовується для асинхронних потоків даних (наприклад, читання файлів, API-потоки).
Ітератор vs Ітерований об'єкт
| Поняття | Що це | Приклад |
|---|---|---|
| Ітерований об'єкт (Iterable) | Об'єкт, у якого є метод [Symbol.iterator]() | масив, рядок, Set |
| Ітератор (Iterator) | Об'єкт, у якого є метод next() | результат виклику arr[Symbol.iterator]() |
Приклад:
const arr = [1, 2, 3];
const iterator = arr[Symbol.iterator](); // ітераторКороткий підсумок
| Термін | Опис |
|---|---|
| Ітератор | Об'єкт з методом next(), який повертає { value, done } |
| Ітерований об'єкт | Об'єкт, який реалізує метод [Symbol.iterator]() |
| done | Прапорець кінця послідовності (true - ітерацію завершено) |
| value | Поточне значення |
| Використовується в | for...of, spread, Array.from(), деструктуризація |
Коротка відповідь
Для співбесідиКоротка відповідь допоможе вам впевнено відповідати на цю тему під час співбесіди.