Skip to main content

Yield у генераторах

1. Що робить yield

yield - це оператор, який повертає значення з функції-генератора назовні і призупиняє виконання до наступного виклику .next().

Тобто:

  • коли генератор "доходить" до yield, він заморожується;
  • коли ми знову викликаємо .next(), він відновлює роботу одразу після того yield, де зупинився.

2. Найпростіший приклад

javascript
function* gen() { console.log('До першого yield'); yield 1; console.log('Між yield'); yield 2; console.log('Після другого yield'); } const it = gen(); console.log(it.next()); // { value: 1, done: false } console.log(it.next()); // { value: 2, done: false } console.log(it.next()); // { value: undefined, done: true }

Що відбувається покроково:

  1. gen() повертає об'єкт-ітератор -> функція ще не запущена.
  2. it.next() -> запускає функцію -> доходить до yield 1, повертає { value: 1 } і заморожується.
  3. Наступний it.next() -> продовжує з того самого місця, після yield 1.
  4. Після другого yield знову "заморожується".
  5. Коли done: true, генератор завершив роботу.

3. Як yield повертає значення

javascript
function* seq() { yield 'A'; yield 'B'; yield 'C'; } const it = seq(); console.log(it.next().value); // "A" console.log(it.next().value); // "B" console.log(it.next().value); // "C" console.log(it.next().done); // true

yield - це "тимчасовий return": він повертає значення, але не завершує функцію.


4. Передача значення назад у генератор через next(value)

yield не тільки повертає дані назовні, а й може приймати значення назад при наступному виклику .next(value).

javascript
function* dialog() { const name = yield 'Як тебе звати?'; yield `Привіт, ${name}!`; } const chat = dialog(); console.log(chat.next().value); // "Як тебе звати?" console.log(chat.next('Tim').value); // "Привіт, Tim!"
  • Перший next() запустив генератор і дійшов до першого yield.
  • Другий next('Tim') передав 'Tim' у генератор - і це значення потрапило в const name.

5. Завершення генератора через return

Коли генератор доходить до кінця, або якщо викликати iterator.return(value), він завершує виконання з done: true.

javascript
function* numbers() { yield 1; yield 2; } const it = numbers(); console.log(it.next()); // { value: 1, done: false } console.log(it.return('stop')); // { value: 'stop', done: true } console.log(it.next()); // { value: undefined, done: true }

6. yield* - делегування іншому генератору

Іноді один генератор може "передати керування" іншому через yield*.

javascript
function* inner() { yield 'B'; yield 'C'; } function* outer() { yield 'A'; yield* inner(); // передає керування іншому генератору yield 'D'; } for (const val of outer()) { console.log(val); }

Вивід:

javascript
A B C D

yield* - це вкладений цикл: "просто yield усі значення іншого генератора".


7. Важливий момент - "лінивість"

yield робить генератори лінивими (lazy) - значення обчислюються тільки за запитом, а не заздалегідь.

javascript
function* range(start, end) { for (let i = start; i <= end; i++) { console.log('Генерую', i); yield i; } } for (const num of range(1, 3)) { console.log('Отримано:', num); }

Вивід:

javascript
Генерую 1 Отримано: 1 Генерую 2 Отримано: 2 Генерую 3 Отримано: 3

Генератор "створює" значення в міру потреби, а не зберігає весь діапазон одразу.


8. Помилки всередині генератора (throw)

Можна "закинути" помилку прямо всередину генератора:

javascript
function* gen() { try { yield 1; } catch (e) { console.log('Помилку спіймано:', e.message); } } const it = gen(); it.next(); it.throw(new Error('Щось не так')); // Помилку спіймано: Щось не так

Підсумок

ОсобливістьОпис
Що робитьПризупиняє виконання і повертає значення
ВідновленняЧерез .next()
Чи можна передавати значення назадТак (next(value))
Чи можна завершитиЧерез return()
Чи можна делегуватиЧерез yield*
ОбчисленняЛіниві
Працює тільки вfunction* (генераторах)

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

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

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