--- sidebar_position: 1 --- # Генераторы Обычные функции возвращают только одно-единственное значение (или ничего). Генераторы могут порождать (yield) множество значений одно за другим, по мере необходимости. Генераторы отлично работают с перебираемыми объектами и позволяют легко создавать потоки данных. - Генераторы создаются при помощи функций-генераторов `function* f(…) {…}`. - Внутри генераторов и только внутри них существует оператор yield. - Внешний код и генератор обмениваются промежуточными результатами посредством вызовов next/yield. В современном JavaScript генераторы используются редко. Но иногда они оказываются полезными, потому что способность функции обмениваться данными с вызывающим кодом во время выполнения совершенно уникальна. И, конечно, для создания перебираемых объектов. ## Функция-генератор Источник: [https://learn.javascript.ru/generators](https://learn.javascript.ru/generators) Для объявления генератора используется специальная синтаксическая конструкция: function*, которая называется «функция-генератор». Основным методом генератора является next(). При вызове он запускает выполнение кода до ближайшей инструкции `yield <значение>` (значение может отсутствовать, в этом случае оно предполагается равным undefined). По достижении yield выполнение функции приостанавливается, а соответствующее значение – возвращается во внешний код: Результатом метода next() всегда является объект с двумя свойствами: - **value**: значение из `yield`. - **done**: `true`, если выполнение функции завершено, иначе `false`. ```js function* generateSequence() { yield 1; yield 2; return 3; } let generator = generateSequence(); let one = generator.next(); alert(JSON.stringify(one)); // {value: 1, done: false} ``` 💥 **function\* f(…) или function \*f(…)** Нет разницы, оба синтаксиса корректны.\ Но обычно предпочтителен первый вариант, так как звёздочка относится к типу объявляемой сущности (function* – «функция-генератор»), а не к её названию, так что резонно расположить её у слова function. ## Перебор генераторов Как вы, наверное, уже догадались по наличию метода next(), генераторы являются перебираемыми объектами. Возвращаемые ими значения можно перебирать через `for..of` Это из-за того, что перебор через `for..of` игнорирует последнее значение, при котором `done: true`. Поэтому, если мы хотим, чтобы были все значения при переборе через `for..of`, то надо возвращать их через `yield`: ```js function* generateSequence() { yield 1; yield 2; yield 3; } let generator = generateSequence(); for(let value of generator) { alert(value); // 1, затем 2, затем 3 } ``` ## yield – дорога в обе стороны `yield` – дорога в обе стороны: он не только возвращает результат наружу, но и может передавать значение извне в генератор. Чтобы это сделать, нам нужно вызвать `generator.next(arg)` с аргументом. Этот аргумент становится результатом `yield`.