Skip to main content

Генератори та ітератори

1. Що таке ітератори (коротко)

Ітератор - це об'єкт, який дозволяє поелементно перебирати значення.

Він повинен реалізовувати метод next(), який повертає об'єкт формату:

javascript
{ value: <значення>, done: <булеве> }

Приклад простого ручного ітератора:

javascript
const iterator = { current: 0, next() { if (this.current < 3) { return { value: this.current++, done: false }; } else { return { value: undefined, done: true }; } } }; console.log(iterator.next()); // { value: 0, done: false } console.log(iterator.next()); // { value: 1, done: false } console.log(iterator.next()); // { value: 2, done: false } console.log(iterator.next()); // { value: undefined, done: true }

Ітератор - це об'єкт, який знає, як видавати значення по одному.


2. Що таке генератор

Генератор (function*) - це зручний спосіб створити ітератор, не реалізуючи next() вручну.

Коли ти викликаєш function*, вона повертає об'єкт-генератор, який вже реалізує ітераторний протокол.


3. Генератор є ітератором

javascript
function* gen() { yield 10; yield 20; yield 30; } const iterator = gen(); 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 }
  • iterator - це об'єкт-генератор;
  • у нього є метод next(), що повертає { value, done };
  • отже, він повністю відповідає протоколу ітератора.

4. Генератор також є ітерованим об'єктом

Генератор реалізує не лише ітераторний, а й ітерований протокол, тому що в нього є метод Symbol.iterator:

javascript
function* gen() { yield 1; yield 2; yield 3; } const it = gen(); console.log(typeof it[Symbol.iterator]); // "function" console.log(it[Symbol.iterator]() === it); // true

Це означає, що генератор:

  • можна використовувати в for...of;
  • можна розпилювати (...);
  • можна передавати в Array.from(), Promise.all() тощо.

5. Приклад використання генератора як ітератора

javascript
function* numbers() { yield 1; yield 2; yield 3; } for (const n of numbers()) { console.log(n); }

Виведе:

javascript
1 2 3

for...of автоматично викликає next() у генератора, поки done: false.


6. Зв'язок між ітераторами і генераторами

ВластивістьІтераторГенератор
Що цеОб'єкт з методом next()Функція, що повертає ітератор
Повертає{ value, done }{ value, done }
Створюється вручнутакні, автоматично
Керує станом вручнутакні, автоматично всередині function*
Можна використовувати в for...ofТільки якщо реалізує [Symbol.iterator]так (реалізовано типово)

Тобто: генератори - це синтаксичний цукор над створенням ітераторів.


7. "Ручний ітератор" vs "генератор"

Без генератора:

javascript
function makeIterator(array) { let i = 0; return { next() { return i < array.length ? { value: array[i++], done: false } : { value: undefined, done: true }; } }; } const it = makeIterator(['a', 'b', 'c']); console.log(it.next()); // { value: 'a', done: false }

З генератором:

javascript
function* makeIterator(array) { for (const item of array) yield item; } const it = makeIterator(['a', 'b', 'c']); console.log(it.next()); // { value: 'a', done: false }

Генератори прибирають усю ручну логіку стану, зберігаючи при цьому ту саму поведінку.


8. Генератори дозволяють створювати "нескінченні ітератори"

javascript
function* infiniteCounter() { let i = 1; while (true) yield i++; } const it = infiniteCounter(); console.log(it.next().value); // 1 console.log(it.next().value); // 2 console.log(it.next().value); // 3

Це неможливо зі звичайним масивом, але ітератори (і генератори) підтримують "ліниву" нескінченність.


ПІДСУМОК

КонцепціяІтераторГенератор
Що цеОб'єкт з методом next()Функція, що повертає ітератор
Керування станомРучнеАвтоматичне
ПротоколІтераторнийІтераторний + Ітерований
Метод Symbol.iteratorЗазвичай потрібно додати вручнуЄ типово
Можна використовувати в for...ofТільки якщо реалізований [Symbol.iterator]завжди
ОбчисленняЛінивіЛіниві
ЗручністьНизькаВисока

Підсумок в одній фразі:

Генератор - це зручний спосіб створити ітератор, не реалізуючи вручну next(), done і внутрішній стан.

Коротка відповідь

Для співбесіди
Premium

Коротка відповідь допоможе вам впевнено відповідати на цю тему під час співбесіди.