简介

Generator 是ES6新增的一种函数,可以看做一个状态机

通常我们通过Generator函数来实现一些异步操作

正文

定义一个Generator函数需要在function关键字后加一个*号

  1. function *f() {
  2. yield 1
  3. yield 2
  4. }
  5. let a = f()
  6. a.next() // {value: 1, done: false}
  7. a.next() // {value: 2, done: false}
  8. a.next() // {value: undefined, done: true}
  9. a.next() // {value: undefined, done: true}

显然我们定义个一个叫做f的Generator函数,那么f可以看做是一个状态机

f的内部我们用 yield 关键字定义了两个 状态

然后我们通过f()执行这个函数,与普通函数不同的是,Generator函数执行后,

得到的结果并不是函数的返回值,而是而是一个代表其内部状态的Iterator

Iterator我们之前已经介绍过了,是一个通用的遍历器接口,我们可以调用它上面的next方法得到其内部的值

yield 命令用在Generator函数体中,与return类似,停止执行函数并把它后面的表达式的值返回

yield 把Generator函数体划分成一块一块来执行,每次调用next方法,都会使函数继续向下执行,直到遇见下一个 yield 并把值放在value里返回

如果后续再没有其他 yield 或return 就把done字段置为true,代表全部的状态都已运行完毕

正常情况下我们不会手动去一次次调用next查看结果,而是使用 for...of 循环:

  1. function *f() {
  2. yield 1
  3. yield 2
  4. }
  5. for(let x of f()){
  6. console.log(x)
  7. }
  8. // 1 2

关于Generator的细节知识点很多,比如next还可以传入参数影响Generator函数内部状态等等

不过时至今日(17年6月),Generator在开发中的应用已经很少了,这里不再为新手介绍其他知识

主流的异步方案已经逐渐成型,目前我们使用Promise和Async来解决异步问题

思考

这部分内容希望你都可以手动敲一遍,独立思考

尝试写出一个表示斐波那契数列的Generator函数

函数接收一个参数,代表生成的斐波那契数列的长度

  1. function* fib(length){
  2. // 做一些操作,然后使用yield返回每一步的结果
  3. }
  4. for(let x of fib(7)){
  5. console.log(x)
  6. }
  7. // 输出 [1, 1, 2, 3, 5, 8, 13]