
Замена встроенному циклу for.
Так как генератор возвращает iterable и yeild* может вернуть каждый отдельный элемент iterable, мы можем создать второй генератор и yield его из второго генератора.
Например, создадим такой генератор
const shoutIterator = function* (word) {
yield word + "!"
yield word + "!!"
yield word + "!!!"
}
И будем использовать его внутри другого генератора:
const reverseIterator = function* (array) {
yield* shoutIterator(array[0])
yield* shoutIterator(array[1])
yield* shoutIterator(array[2])
}
Что даст нам примерно такой результат:
const abcs = ["A", "B", "C"]
const iterator = reverseIterator(abcs)
for (let value of iterator) {
console.log(value)
}
В консоли:
- «A!»
- «A!!»
- «A!!!»
- «B!»
- «B!!»
- «B!!!»
- «C!»
- «C!!»
- «C!!!»
Такой же результат мы могли бы получить с помощью встроенного цикла for но генераторы дают нам более простую логику и уменьшают сложность алгоритма.
Как генератор работает внутри.
После каждого yeild генератор ставит свое исполнение на паузу. Например после выполнения этого кода
function* generator() {
//first iteration
yield 1
console.log("one")
}
const iterator = generator()
console.log(iterator.next())
В консоли:
[object Object] {
done: false,
value: 1
}
Но не результат вывода console.log(«one»).
Есдли мы добавим следующий вызов итератора console.log(iterator.next() тогда мы увидим в консоли «one» и {done: true, value: undefined}.
Используем генератор как замыкание.
Стандартное замыкание выглядит примерно так:
function makeAdder(x) {
return function (y) {
return x + y
}
}
Что позволяет захватывать значение Х во вложенной функции и выводит 3 в консоль в результате использования:
let add2 = makeAdder(2)
console.log(add2(1))
Мы можем заменить замыкание на генератор:
function* makeAdderGenerator(x) {
let y = yield x
while (true) {
y = yield x + y
}
}
let add2Iterator = makeAdderGenerator(2)
console.log(add2Iterator.next())
console.log(add2Iterator.next(1))
console.log(add2Iterator.next(2))
Что даст в консоли такой результат:
- [object Object] {
done: false,
value: 2
} - [object Object] {
done: false,
value: 3
} - [object Object] {
done: false,
value: 4
}
Может показаться, что использование while приведет к бесконечному циклу, но это не так, так как после каждого выполнения yeild цикл ставится на паузу.
Используем генератор для создания функции, заполняющей диапазон.
Как вы уже поняли, генераторы отлично подходят для генерации данных, поэтому мы можем использовать генератор так же следующим образом:
function* range(start, end) {
while (start < end) yield start++
}
console.log([...range(0, 10)])
Что даст в консоли массив чисел от 0 до 9.

Оставить комментарий