Кратко
Generator — функция, которая может приостановить выполнение (yield) и возобновить (next()). Генератор возвращает итератор: next() возвращает {value, done}. yield — точка приостановки. for...of работает с итераторами автоматически.
Подробно
Создание генератора: function* count() { yield 1; yield 2; yield 3; }
const gen = count(); console.log(gen.next()); // { value: 1, done: false } console.log(gen.next()); // { value: 2, done: false } console.log(gen.next()); // { value: 3, done: false } console.log(gen.next()); // { value: undefined, done: true }
yield — точка приостановки: function* range(start, end) { for (let i = start; i <= end; i++) { yield i; } }
for (const num of range(1, 5)) { console.log(num); // 1, 2, 3, 4, 5 }
yield* — делегирование: function* concat(iter1, iter2) { yield* iter1; yield* iter2; }
// Кастомный итератор: class Fibonacci { constructor(limit) { this.limit = limit; } [Symbol.iterator]() { let a = 0, b = 1, count = 0; const limit = this.limit; return { next() { if (count >= limit) return { done: true }; const value = a; [a, b] = [b, a + b]; count++; return { value, done: false }; } }; } }
for (const n of new Fibonacci(5)) { console.log(n); // 0, 1, 1, 2, 3 }
Ментальная модель
Generator — как книга с закладками. yield — закладка: «Прочитай до сюда, потом вернись». next() — «Продолжи читать от последней закладки». Когда книга закончена — done: true.
Примеры
**Самый простой:**
function* oneTwo() {
yield 1;
yield 2;
}
const gen = oneTwo();
console.log(gen.next()); // { value: 1, done: false }
console.log(gen.next()); // { value: 2, done: false }
console.log(gen.next()); // { value: undefined, done: true }Простейший генератор: два yield.
**Простой:**
function* fibonacci() {
let a = 0, b = 1;
while (true) {
yield a;
[a, b] = [b, a + b];
}
}
const fib = fibonacci();
for (let i = 0; i < 8; i++) {
console.log(fib.next().value); // 0, 1, 1, 2, 3, 5, 8, 13
}Бесконечный генератор: Fibonacci без ограничения.
**Реальный пример:**
// Генератор для чтения файла построчно
function* readLines(text) {
const lines = text.split('\n');
for (let i = 0; i < lines.length; i++) {
yield { lineNumber: i + 1, content: lines[i] };
}
}
const csv = 'Name,Age\nАнна,25\nБорис,30';
for (const line of readLines(csv)) {
console.log(`${line.lineNumber}: ${line.content}`);
}
// 1: Name,Age
// 2: А́нна,25
// 3: Борис,30Генератор для обработки данных построчно.
Частые ошибки
**Неправильно:** Думать, что yield останавливает весь код
**Почему:** yield останавливает ТОЛЬКО генератор. Остальной код продолжает выполняться.
**Правильно:** yield = пауза внутри генератора, не во всём приложении.
**Неправильно:** Забывать, что генератор — итератор
**Почему:** Генератор возвращает объект с методом next() и Symbol.iterator.
**Правильно:** Генератор = итератор по умолчанию. Можно использовать в for...of.
Важно запомнить
- function* создаёт генератор
- yield — точка приостановки и возврат значения
- next() возобновляет выполнение
- Генератор = итератор (Symbol.iterator)
- yield* делегирует другой итератор
Связь
Назад: Вы знаете перебираемые значения (JI19) и функции (J9). Генераторы объединяют оба понятия.
Вперёд: Следующий урок (JV9) — асинхронные генераторы — сочетание генераторов с Promise.