Generators
В одной фразе: генератор — функция, которая может приостанавливаться через yield и возобновляться, сохраняя весь локальный стек между вызовами. На собесе проверяют двустороннюю коммуникацию через next(value), методы return()/throw() и паттерны lazy evaluation.
// Двусторонняя коммуникация: next(value) передаёт значение в yieldfunction* dialog() { const name = yield 'What is your name?'; // пауза 1: отдаём вопрос const color = yield `Hi ${name}! Fav color?`; // пауза 2 return `${name} likes ${color}`; // done: true}
const gen = dialog();gen.next(); // { value: 'What is your name?', done: false }gen.next('Alice'); // { value: 'Hi Alice! Fav color?', done: false }gen.next('blue'); // { value: 'Alice likes blue', done: true }gen.next(); // { value: undefined, done: true } — уже завершён// Lazy sequences: вычисляется только по требованиюfunction* fibonacci() { let [a, b] = [0, 1]; while (true) { yield a; [a, b] = [b, a + b]; }}
function* take(gen, n) { for (const val of gen) { yield val; if (--n <= 0) return; }}
[...take(fibonacci(), 8)]; // [0, 1, 1, 2, 3, 5, 8, 13]// yield* делегирует в другой iterable/generatorfunction* flatten(arr) { for (const item of arr) { if (Array.isArray(item)) yield* flatten(item); // рекурсивно else yield item; }}[...flatten([1, [2, [3, 4]], 5])]; // [1, 2, 3, 4, 5]
// return() и throw() управляют генератором извнеconst gen = fibonacci();gen.next(); // { value: 0, done: false }gen.return(99); // { value: 99, done: true } — принудительное завершениеgen.next(); // { value: undefined, done: true } — уже завершён// gen.throw(err) // бросает ошибку в точку yieldИтог: Генераторы — строительный блок для корутин, lazy evaluation и state machines. async/await реализован поверх генераторов внутри движка.