生成器基础
可以在任意函数声明处使用*从而声明一个生成器函数,生成器函数的执行会产生一个生成器对象,调用生成器函数时,并不执行,只在第一次调用next方法时真正开始执行生成器函数内部语句。在遇到yield时停止。
箭头函数无法声明为生成器函数
关键点
- yield关键字可以让生成器停止和开始执行,是一个关键点。
- 遇到yield后,执行会停止,函数作用域的状态会被保留。
- 想恢复执行,只能在生成器对象上调用next()方法恢复执行。
- 返回的情况
- yield关键字有点像一个“中间”返回语句,它生成的值会出现在next方法返回的对象里。
- 通过yield关键字退出的生成器函数会处于done:false状态
- 通过return关键字退出的生成器函数会处于done:true状态
- 生成器对象作为可迭代对象
使用yield实现输入和输出
除了可以作为函数的中间返回语句使用,yield关键字还可以作为函数的中间参数使用。next方法的第一个参数会传给yield关键字,但是第一次next方法传入的值不会被使用,因为第一次next是开始执行生成器函数。
- 当遇到第一个yield时,第一个yield会将后面的值返回,next方法接受的第一个参数对第一个yield无效;此时返回了第一个yield后面的值
- 如果再次执行next方法并传入值,那么生成器内部会接受该值,并且yield 表达式本身会被赋该值,但是返回值依然是yield后面的值。
- 额外的,如果yield值后面没有值,那么就代表该中间返回语句没有返回值。
function *test(){
console.log(yield 'a')
console.log(yield)
}
const d = test()
d.next()
{value: 'a', done: false}
d.next('c')
c
{value: undefined, done: false}
使用*号增强yield行为
function* generatorFn() {
console.log('iter value:', yield* [1, 2, 3]);
}
for (const x of generatorFn()) {
console.log('value:', x);
}
两种行为
- yield * 后面的是可迭代对象,并且等同于使用yield抛出每个值,实质是将一个可迭代对象序列化为一连串单独产出的值,等于循环yield value
- yield * 本身返回值是根据生成器函数最终是否return值而定的,如果没有则是undefined
生成器作为默认迭代器
使用增强(* 可迭代对象) 实现 [Symbol iterator] () 方法
提前终止的生成器
终止分为两个情况:提前关闭和错误终止
每个生成器对象都有return方法和throw方法
- return 方法会将传入的值作为生成器最后的返回值(done:true,value: return方法传入的值)
- throw方法会将传入的值作为错误,在生成器函数内部,如果处理了错误,那么next方法将跳过本次yield,返回的结果是下一次yield的结果。如果没有处理,生成器对象会马上进入closed状态,即被关闭