Генераторы
Генераторы - это специальный тип функции, который работает как фабрика итераторов.
Функция становится генератором, если содержит один или более yield
операторов и использует function*
синтаксис.
Способы обьъявления
1function* generator(){2function *generator(){}3function * generator(){}4const myGenerator = function *(){}56class MyClass{7 *generator(){}8}910const MyObj = {11 *generator(){12}
Важно
Когда мы вызываем функцию-генератор, она возвращает нам объект-итератор.
Отличие от обычных функций
function
- Обычные функции возвращают только одно-единственное значение (или ничего).
function*
- Генераторы могут порождать (
yield
) множество значений одно за другим, по мере необходимости. - Генераторы Отлично работают с перебираемыми объектами и позволяют легко создавать потоки данных.
- Генераторы могут приостанавливать своё выполнение, возвращать промежуточный результат и далее возобновлять его позже, в произвольный момент времени.
1function* simpleGenerator() {2 yield "simple";3 yield "generator";4}56const it = simpleGenerator();7console.log(it.next()); // {value: 'simple, done: false}8console.log(it.next()); // {value: 'generator, done: false}9console.log(it.next()); // {value: undefined, done: true}
yield
- приостанавливает выполнение функции и возвращает некое значение.
Итераторы и генераторы могут обмениваться данными в двух направлениях.
А именно, генераторы, с помощью ключевого слова yield
, могут возвращать значения итераторам, однако и итераторы могут отправлять данные генераторам, используя метод iterator.next('someValue')
1function* favBeer() {23 const reply = yield "What is your favorite type of beer?";4 console.log(reply);56 if (reply !== "ipa") return "No soup for you!";78 return "OK, soup.";9}1011const it = favBeer();12const q = it.next().value; // Итератор задаёт вопрос13console.log(q);14const a = it.next("lager").value; // Получен ответ на вопрос15console.log(a);1617// What is your favorite beer?18// lager19// No soup for you!
Замена RangeIterator из лекции про итераторы на генератор createRangeGenerator
1function* createRangeGenerator(start, stop) {2 for (var i = start; i <= stop; i++) {3 yield i;4 }5}67const range = createRangeGenerator(1, 3);89console.log(range.next().value); // 110console.log(range.next().value); // 211console.log(range.next().value); // 312console.log(range.next().done); // true
Практика 👨💻👨💻
Задание 1
- создать
createСalendarGenerator
Задание 2
class MonthIterator
Воспользовавшись заданием из практики CalendarIterator
переделать CalendarIterator
так что бы он возвращал MonthIterator
значением итератора
создать MonthIterator
Приватные поля:
- name
- days
Публичные поля:
- next
- toString
MonthIterator
Должен итерировать дни месяца учитывая, что каждый месяц имеет не равное количество дней.
1class CalendarIterator{}23const calendar = new CalendarIterator(1, 2);4console.log(calendar.next().value); // MonthIterator56const month = calendar.next().value78console.log(month.toString()) // name of month9console.log(month.next().value) // 110console.log(month.next().value) // 211console.log(month.next().value) // 3