Skip to content

generator

解决了什么问题?

  1. 简化多层 for 循环引用(出自理解 es6 第八章)

迭代器(iterator)是什么

  1. 迭代器具有 next 方法的特殊对象
  2. 特殊对象调用 next 方法会返回一个结果对象
  3. 结果对象包含 value,done 两个属性
    1. value 代表特殊对象的迭代值
    2. done 表示特殊对象是否迭代完成
  4. 当特殊对象调用 next 到最后一个值后,继续调用 next,返回的结果对象为
    1. value 是 next 函数默认的 return 值
    2. done 为 true

基于上述规则可实现一个迭代器函数,将数组转换为迭代器。

生成器(generator)

es6 提供生成器语法避免手动创建迭代器的复杂性。

js
// 1. 在函数关键字后加上 * 申名函数为迭代器
function * iteratorDemo() {
    // 2. 采用 yield 语法申名每次 next 返回的内容
    yield 1
    yield 2
}
  1. *, function 关键字后的星号指明为迭代器函数
  2. yield, 函数体中的 yield 关键字指明每个 next 的返回内容

yield

yield 关键字可用于,值和表达式之前。可以在语句内部使用该关键字。 采用迭代器语法,修改数组转换为迭代启动方法。

js
function * iteratorArr(arr) {
    for(let i =0;i++;i< arr.length) {
        yield arr[i]
    } 
}

注意 yield 的所属的函数体必须为生成器函数,无法用于其他函数体内部。

由于生成器是一个函数,可采用函数表达式声明生成器,也可在 对象内部,采用简写模式直接申名。

js
// 函数表达式创建生成器
const iteratorArr = function * iteratorArr(arr) {
    for(let i =0;i++;i< arr.length) {
        yield arr[i]
    } 
}

// 对象内部采用简写申名生成器
let obj = {
    // 生成器
    *iterator {

    }
}

注意箭头函数不支持生成器语法

知识点

  1. 生成器构造函数

  2. 生成器对象 generator, GeneratorFunction

    js
    // 1. 函数关键字后加 * 号申名生成器函数
    function* a() {
      // 2. yield 用在值和表达式之前,申名迭代位置
      yield 1
    
    }
    1. 利用 throw 抛出错误
    2. next 支持传值
    3. next 为惰性求值
  3. 代理生成器,可采用 yield * 定义代理迭代器

  4. 使用场景, 迭代器改变了数据和值的消费模式,消费者可以依据值的生产速度消费结果

    1. 任务调度,函数暂停的协程功能,详见 迭代器调度
    2. 无限状态机
  5. es6 迭代器如何转为 es5,详见 regenerator

参考迭代器规范

参考资料