迭代器iterator;生成器generator;yield;yield *;

疑问:

  • generator是ES6出的,但ES5没有迭代器么?数组的遍历什么的怎么实现呢?

    • 答:ES5没有迭代器,所以在写循环的时候都是用传统的数字标识元素位置。

      心得&书摘

      关于迭代器和生成器,最好结合《深入理解ES6》一同学习。

      1 迭代器模式

  • 可迭代对象:可理解成数组或是集合

  • 迭代器(iterator)
    • 按需创建的一次性对象
    • 每个迭代器都会关联一个可迭代对象
    • 使用next()方法在可迭代对象中遍历数据
  • 看起来迭代器的应用场景是和生成器generator绑定的,但其实这是所有可迭代对象通用的:

    接收可迭代对象的原生语言特性包括: ❑ for-of循环 ❑ 数组解构 ❑ 扩展操作符 ❑ Array.from() ❑ 创建集合 ❑ 创建映射 ❑ Promise.all()接收由期约组成的可迭代对象 ❑ Promise.race()接收由期约组成的可迭代对象 ❑ yield*操作符,在生成器中使用

  • 书中关于迭代器的描述十分深入,这里不做展开

    提前终止迭代器

  • 可能的情况包括:

    • for-of循环通过break、continue、return或throw提前退出;
    • 解构操作并未消费所有值。
  • 数组的迭代器无法关闭

    2 生成器

  • 特性

    • ES6新增。
    • 可以在函数块内暂停和恢复代码执行。
    • 生成器的形式是一个函数,函数名称前面加一个星号(*)表示它是一个生成器。
  • 箭头函数不能用来定义生成器函数。
  • 可实现自定义迭代器、实现协程。
  • 与《你不知道的javascript》(中卷)存在差异:
    • 红宝书:生成器创建生成器对象,生成器对象类似迭代器,实现了Iterator接口。
    • you don’t know js:生成器创建迭代器对象。
    • 我的见解:红宝书的写法更易懂,you don’t know js有点逻辑跳脱,容易混淆。
  • 生成器函数只会在初次调用next()方法后开始执行

    yield

  • yield关键字可以让生成器停止和开始执行

  • 遇到这个关键字后,执行会停止,函数作用域的状态会被保留。
  • 停止执行的生成器函数只能通过在生成器对象上调用next()方法来恢复执行
  • yield关键字必须直接位于生成器函数定义中,出现在嵌套的非生成器函数中会抛出语法错误
    • 放在数组的迭代方法里也会出错
  • yield可实现输入和输出
  • 将生成器对象当成可迭代对象

    • 红包书在这里才将生成器对象与迭代器对象相联系,存在一个过渡过程。但不得不说正是因此,这本书很多地方过于严谨,阅读感受晦涩难懂。
    • 自定义可迭代对象时很有用
    • image.png

      yield*

  • 可以使用星号增强yield的行为,让它能够迭代一个可迭代对象

    • image.png
  • 最有用的地方是实现递归操作,此时生成器可以产生自身

    • image.png

      提前终止生成器

  • return()和throw()方法都可以用于强制生成器进入关闭状态。

  • 只要通过return()进入关闭状态,就无法恢复了。
  • 通过throw()方法,若错误在生成器内部未处理,则会进入关闭状态。
    • 如果生成器对象还没有开始执行,那么调用throw()抛出的错误不会在函数内部被捕获,因为这相当于在函数块外部抛出了错误。