Запропонувати правкуПокращити цю статтюДопрацюйте відповідь до «Що таке генератор (function*)?». Ваші зміни проходять модерацію перед публікацією.Потрібне підтвердженняКонтентЩо ви змінюєте🇺🇸EN🇺🇦UAПереглядЗаголовок (UA)Коротка відповідь (UA)**Генератор** - це функція, яка може призупиняти своє виконання і повертати проміжні значення, а потім продовжувати роботу з того самого місця. **Ключове:** `function*` повертає спеціальний об'єкт-ітератор, а `yield` призупиняє виконання, повертає значення назовні й дозволяє передати значення назад усередину при наступному виклику `.next()`.Показується над повною відповіддю для швидкого нагадування.Відповідь (UA)Зображення## Що таке генератор (`function*`) **Генератор** - це функція, яка **може призупиняти своє виконання** і **повертати проміжні значення**, а потім **продовжувати роботу з того самого місця**. Формально: > `function*` повертає спеціальний об'єкт - **ітератор**, який керує виконанням функції. --- ## Як оголошується генератор ```javascript function* myGenerator() { yield 1; yield 2; yield 3; } ``` При виклику `myGenerator()` **не виконується сам код** функції! Вона повертає **ітератор**, який потрібно "прокручувати" вручну: ```javascript const gen = myGenerator(); 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` призупиняє виконання і повертає значення. --- ## Що робить `yield` Оператор `yield`: 1. **Призупиняє виконання** функції; 2. **Повертає значення** назовні (у `.next()`); 3. Дозволяє **передати значення назад усередину** при наступному виклику `.next()`. --- ### Приклад 1 - проста послідовність: ```javascript function* counter() { yield 1; yield 2; yield 3; } const gen = counter(); 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 } ``` --- ### Приклад 2 - паузи між кроками ```javascript function* steps() { console.log("Крок 1"); yield; console.log("Крок 2"); yield; console.log("Крок 3"); } const gen = steps(); gen.next(); // "Крок 1" gen.next(); // "Крок 2" gen.next(); // "Крок 3" ``` Тут `yield` використовується **без значення** - просто як "точка зупинки". --- ## Як передати значення назад у генератор Коли ти викликаєш `gen.next(value)`, це `value` **потрапляє всередину генератора**, у те місце, де він був призупинений `yield`. ### Приклад 3 - передача значення назад ```javascript function* dialog() { const name = yield "Як тебе звати?"; const age = yield `Привіт, ${name}! Скільки тобі років?`; yield `Тобі ${age} років.`; } const gen = dialog(); console.log(gen.next()); // { value: "Як тебе звати?", done: false } console.log(gen.next("Oleh")); // { value: "Привіт, Oleh! Скільки тобі років?", done: false } console.log(gen.next(25)); // { value: "Тобі 25 років.", done: false } console.log(gen.next()); // { value: undefined, done: true } ``` Пояснення: - Перший `next()` запускає генератор і повертає перший `yield`. - Другий `next("Oleh")` *вставляє значення* `"Oleh"` у місце, де стояв перший `yield`. - Третій `next(25)` вставляє `25` у місце другого `yield`. --- ## Приклад 4 - генератор з нескінченною послідовністю ```javascript function* infinite() { let i = 0; while (true) { yield i++; } } const gen = infinite(); console.log(gen.next().value); // 0 console.log(gen.next().value); // 1 console.log(gen.next().value); // 2 ``` Генератори ідеально підходять для **лінивих обчислень** - коли тобі потрібно "порційно" видавати дані без створення величезних масивів. --- ## Керування генератором | Метод | Що робить | |---|---| | `.next(value)` | Продовжує виконання й повертає наступний `{ value, done }` | | `.return(value)` | Примусово завершує генератор, повертає `{ value, done: true }` | | `.throw(error)` | Кидає виняток усередину генератора, який можна спіймати всередині `try...catch` | --- ### Приклад 5 - `return()` і `throw()` ```javascript function* process() { try { yield "Крок 1"; yield "Крок 2"; } catch (e) { console.log("Помилка:", e.message); } finally { console.log("Генератор завершено"); } } const gen = process(); console.log(gen.next()); // { value: "Крок 1", done: false } console.log(gen.throw(new Error("Щось пішло не так"))); // Помилка: Щось пішло не так // Генератор завершено ``` --- ## Генератори - це ітератори Генератор **автоматично реалізує інтерфейс ітератора** (`next()`) і **ітерованого об'єкта** (`[Symbol.iterator]`). ```javascript function* numbers() { yield 1; yield 2; yield 3; } for (const n of numbers()) { console.log(n); // 1, 2, 3 } ``` --- ## Генератори та асинхронність (бонус) До появи `async/await` генератори використовували для асинхронного коду (через бібліотеки на кшталт `co`). ```javascript function* getData() { const user = yield fetch('/user'); const posts = yield fetch(`/posts?user=${user.id}`); return posts; } ``` Пізніше на їхній основі й з'явився `async/await` (по суті, "автоматизовані генератори"). --- ## Підсумок | Поняття | Опис | |---|---| | `function*` | Оголошення генератора | | `yield` | Призупиняє виконання й повертає значення | | `.next(value)` | Відновлює виконання, передаючи `value` всередину | | `.return(value)` | Завершує генератор | | `.throw(error)` | Кидає виняток у генератор | | **Генератор** | Об'єкт-ітератор, який можна призупиняти й продовжувати |Для рев’юераПримітка для модератора (необов’язково)Бачить лише модератор. Прискорює рев’ю.