生成器函数
一、虽然自定义的迭代器是一个有用的工具,但由于需要显式地维护其内部状态,因此需要谨慎地创建。
二、生成器函数提供了一个强大的选择:它允许你定义一个包含自有迭代算法的函数,同时它可以自动维护自己的状态。
三、生成器函数使用function*语法编写。
四、最初调用时,生成器函数不执行任何代码,而是返回一种称为Generator的迭代器。通过调用生成器的下一个方法消耗值时,Generator函数将执行,直到遇到yield关键字。
五、可以根据需要多次调用该函数,并且每次都返回一个新的Generator,但每个Generator只能迭代一次。
【实例1】此代码的行为是相同的,但实现更容易编写和读取。
function* makeRangeIterator(start = 0, end = Infinity, step = 1) {
for (let i = start; i < end; i += step) {
yield i;
}
}
var a = makeRangeIterator(1,10,2)
a.next() // {value: 1, done: false}
a.next() // {value: 3, done: false}
a.next() // {value: 5, done: false}
a.next() // {value: 7, done: false}
a.next() // {value: 9, done: false}
a.next() // {value: undefined, done: true}
高级生成器
一、生成器会按需计算它们的产生值,这使得它们能够有效地表示一个计算成本很高的序列,甚至是一个无限序列。
二、The next()方法也接受一个参数用于修改生成器内部状态。传递给next()的参数值会被yield接收。
1、传给第一个next()的值会被忽略。
【实例1】下面是斐波那契数列生成器,它使用了next(x)来重新启动序列
function* fibonacci() {
var fn1 = 0
var fn2 = 1
while (true) {
var current = fn1
fn1 = fn2
fn2 = current + fn1
var reset = yield current
if (reset) {
fn1 = 0
fn2 = 1
}
}
}
var sequence = fibonacci()
console.log(sequence.next().value) // 0
console.log(sequence.next().value) // 1
console.log(sequence.next().value) // 1
console.log(sequence.next().value) // 2
console.log(sequence.next().value) // 3
console.log(sequence.next().value) // 5
console.log(sequence.next().value) // 8
console.log(sequence.next(true).value) // 1
console.log(sequence.next().value) // 1
console.log(sequence.next().value) // 1
console.log(sequence.next().value) // 2
三、可以通过调用throw()方法强制生成器抛出异常,并传递应该抛出的异常值。
1、这个异常值从当前挂起的生成器的上下文中抛出,就好像当前挂起的yield是一个throw value 语句。
四、如果在抛出的异常处理期间没有遇到yield,则异常将通过调用throw()向上传播,对next()的后续调用将导致done属性为true。
五、生成器具有return(value)方法,返回给定的值并完成生成器本身。