JavaScript生成器(generator)-入门

150 阅读2分钟

前言

生成器是一种极为灵活的代码结构,拥有在一个函数块内暂停和恢复执行的能力

生成器函数和生成器对象

实现生成器结构很简单,只需要在函数名称前面加上一个*号就代表它是一个生成器函数,只要是定义函数或者方法的地方都可以,除了箭头函数

function* generatorFn() {}
const gen = generatorFn()
console.log(gen)

上面我们定义了一个生成器函数,执行它会返回一个生成器对象,生成器对象是一个可迭代对象,因为它的原型链上的对象实现了迭代协议,我们可以在控制台打印输出一下

截屏2022-04-12 下午12.31.19.png 那么我们可以尝试调用一下它的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>}

查看上述代码,我们可以得知生成器结构的执行机制如下:

  1. 第一次调用生成器函数只会返回生成器对象,成器函数只有在调用了生成器对象的next()方法之后才会开始执行,start字符串在第一次调用next()方法后才被打印出来
  2. 调用next()执行后,生成器函数会执行到yield关键字后停止,并返回yield关键字后面的值作为迭代器结果的value
  3. 当最后一个yield语句执行完成,然后继续调用next(),就会执行return,迭代器结果对象会返回迭代完成,值为return后面的值,此时生成器对象的状态也由一开始的suspended变成了closed

总结

本文大概介绍了生成器结构的相关概念,包括生成器函数,生成器对象,生成器的执行机制,如果想要对生成器有更加深入,更加系统的了解,可以看看文末推荐的参考文献,后续也会出一篇生成器深入的博客

参考文献