Генераторы

Модуль 1: Web Core
23 уровень , 1 лекция
Открыта

2.1 Синтаксис генераторов

Генераторы в JavaScript представляют собой специальные функции, которые позволяют управлять выполнением кода. Они могут приостанавливать свое выполнение и возобновлять его позже, что делает их мощным инструментом для работы с асинхронным кодом, итераторами и другими сложными задачами.

Генераторы определяются с помощью функции function* (обратите внимание на звездочку). Внутри генератора используется оператор yield для приостановки выполнения и возврата значения.

Объявление генератора:

JavaScript
    
      function* generatorFunction() {
        yield 1;
        yield 2;
        yield 3;
      }
    
  

Создание объекта генератора

Вызов генератора не выполняет его тело сразу. Вместо этого он возвращает объект генератора, который можно использовать для итерации по значениям:

JavaScript
    
      const gen = generatorFunction();
    
  

2.2 Использование генераторов

Метод next()

Метод next() используется для возобновления выполнения генератора до следующего оператора yield. Он возвращает объект с двумя свойствами:

  • value: значение, переданное оператором yield
  • done: логическое значение, указывающее, завершен ли генератор (true) или нет (false)

Пример использования метода next():

JavaScript
    
      function* generatorFunction() {
        yield 1;
        yield 2;
        yield 3;
      }

      const gen = generatorFunction();

      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 }
    
  

Итерация по генератору

Генераторы могут использоваться с циклом for...of для итерации по значениям.

Пример итерации по генератору:

JavaScript
    
      function* generatorFunction() {
        yield 1;
        yield 2;
        yield 3;
      }

      const gen = generatorFunction();

      for (const value of gen) {
        console.log(value);
      }

      // Выведет: 1
      // Выведет: 2
      // Выведет: 3
    
  

Пример возврата значений

Генераторы могут возвращать значение с помощью оператора return:

JavaScript
    
      function* generatorFunction() {
        yield 1;
        yield 2;
        return 3;
        yield 4; // Этот yield никогда не будет выполнен
      }

      const gen = generatorFunction();

      console.log(gen.next()); // { value: 1, done: false }
      console.log(gen.next()); // { value: 2, done: false }
      console.log(gen.next()); // { value: 3, done: true }
      console.log(gen.next()); // { value: undefined, done: true }
    
  

2.3 Сложное использование генераторов

Взаимодействие с генератором

Метод next() может принимать аргумент, который передается в генератор и может использоваться внутри него.

Пример передачи значений в генератор:

JavaScript
    
      function* generatorFunction() {
        const value1 = yield 1;
        const value2 = yield value1 + 2;
        yield value2 + 3;
      }

      const gen = generatorFunction();

      console.log(gen.next()); // { value: 1, done: false }
      console.log(gen.next(10)); // { value: 12, done: false }
      console.log(gen.next(20)); // { value: 23, done: false }
      console.log(gen.next()); // { value: undefined, done: true }
    
  

Обработка ошибок

Генераторы позволяют обрабатывать ошибки с помощью блока try...catch.

Пример обработки ошибок:

JavaScript
    
      function* generatorFunction() {
        try {
          yield 1;
          yield 2;
        } catch (error) {
          console.log('Error caught:', error);
        }
      }

      const gen = generatorFunction();

      console.log(gen.next()); // { value: 1, done: false }
      console.log(gen.throw(new Error('Something went wrong'))); // Error caught: Error: Something went wrong

      // { value: undefined, done: true }
    
  

Пример генератора для создания бесконечной последовательности

Генераторы могут использоваться для создания бесконечных последовательностей значений:

JavaScript
    
      function* infiniteSequence() {
        let i = 0;
        while (true) {
          yield i++;
        }
      }

      const gen = infiniteSequence();

      console.log(gen.next().value); // 0
      console.log(gen.next().value); // 1
      console.log(gen.next().value); // 2

      // и так далее
    
  

2.4 Примеры практического использования

Пример 1: Генератор для итерации по объекту

JavaScript
    
      function* objectEntries(obj) {
        const keys = Object.keys(obj);
        for (const key of keys) {
          yield [key, obj[key]];
        }
      }

      const obj = { a: 1, b: 2, c: 3 };
      const gen = objectEntries(obj);

      for (const [key, value] of gen) {
        console.log(`${key}: ${value}`);
      }

      // Выведет:
      // a: 1
      // b: 2
      // c: 3
    
  

Пример 2: Генератор для реализации простого итератора

JavaScript
    
      const myIterable = {
        *[Symbol.iterator]() {
          yield 1;
          yield 2;
          yield 3;
        }
      };

      for (const value of myIterable) {
        console.log(value);
      }

      // Выведет: 1
      // Выведет: 2
      // Выведет: 3
    
  

Генераторы в JavaScript представляют собой мощный инструмент для управления выполнением кода, создания итераторов и работы с асинхронными операциями. Понимание синтаксиса и использования генераторов помогает создавать более гибкий и читаемый код, особенно при работе с последовательностями данных и асинхронными задачами.

1
Задача
Модуль 1: Web Core, 23 уровень, 1 лекция
Недоступна
Генератор чисел
Генератор чисел
1
Задача
Модуль 1: Web Core, 23 уровень, 1 лекция
Недоступна
Динамический генератор
Динамический генератор
Комментарии (2)
ЧТОБЫ ПОСМОТРЕТЬ ВСЕ КОММЕНТАРИИ ИЛИ ОСТАВИТЬ КОММЕНТАРИЙ,
ПЕРЕЙДИТЕ В ПОЛНУЮ ВЕРСИЮ
Gans Electro Уровень 4
11 декабря 2025
Не очень понятно что это было, полезны только первый и последние абзацы. Примеры недостаточно показывают для чего это нужно
Gans Electro Уровень 4
12 декабря 2025
Короче yield работает в обе стороны как тоннель. Он и принимает и передает. 👈 внутрь: получает аргумент из next() 👉 наружу: отдаёт значение

// точка продолжения после предыдущего yield
increment = 5; //Здесь yield принимает 5 внутрь в переменную

currentValue = currentValue + increment; // 10 + 5 = 15

// следующая итерация цикла
yield 15; // возвращаем наружу значение как return 15;
// ... стоп, ждём next()