前言
生成器是一种极为灵活的代码结构,拥有在一个函数块内暂停和恢复执行的能力
生成器函数和生成器对象
实现生成器结构很简单,只需要在函数名称前面加上一个*号就代表它是一个生成器函数,只要是定义函数或者方法的地方都可以,除了箭头函数
function* generatorFn() {}
const gen = generatorFn()
console.log(gen)
上面我们定义了一个生成器函数,执行它会返回一个生成器对象,生成器对象是一个可迭代对象,因为它的原型链上的对象实现了迭代协议,我们可以在控制台打印输出一下
那么我们可以尝试调用一下它的next()方法
function* generatorFn() {}
const gen = generatorFn()
console.log(gen.next()) // {value: undefined, done: true}
我们可以发现next()方法成功调用并返回了一个迭代器结果对象,并且迭代已经完成;按道理应该是先调用其Symbol.iterator方法得到其迭代器对象然后再去调用迭代器对象的next()方法的,但是生成器对象和其迭代器对象又是自引用的,所以我们可以直接调用next()
function* generatorFn() {}
const gen = generatorFn()
console.log(gen === gen[Symbol.iterator]()) // true
yield关键字和生成器结构的执行机制
生成器函数可以通过yeild
关键字来让函数停止执行
function* generatorFn() {
console.log('start')
yield 'a'
yield 'b'
yield 'c'
return 'end'
}
const gen = generatorFn() // generatorFn {<suspended>}
console.log(gen) // start
console.log(gen.next()) // {value: 'a', done: false}
console.log(gen.next()) // {value: 'b', done: false}
console.log(gen.next()) // {value: 'c', done: false}
console.log(gen.next()) // {value: 'end', done: true}
console.log(gen) // generatorFn {<closed>}
查看上述代码,我们可以得知生成器结构的执行机制如下:
- 第一次调用生成器函数只会返回生成器对象,成器函数只有在调用了生成器对象的next()方法之后才会开始执行,start字符串在第一次调用next()方法后才被打印出来
- 调用next()执行后,生成器函数会执行到yield关键字后停止,并返回yield关键字后面的值作为迭代器结果的value
- 当最后一个yield语句执行完成,然后继续调用next(),就会执行return,迭代器结果对象会返回迭代完成,值为return后面的值,此时生成器对象的状态也由一开始的suspended变成了closed
总结
本文大概介绍了生成器结构的相关概念,包括生成器函数,生成器对象,生成器的执行机制,如果想要对生成器有更加深入,更加系统的了解,可以看看文末推荐的参考文献,后续也会出一篇生成器深入的博客
参考文献
- JavaScript高级程序设计
- 你不知道的js(下)
- JavaScript忍者秘籍
- es6.ruanyifeng.com/#docs/gener…
- developer.mozilla.org/zh-CN/docs/…