JavaScript 迭代器与生成器详解

2022-09-15 03:35:27

生成器

一个语法糖, 本质还是一个函数

function* g() {}
const it = g()
console.log(it) // Object [Generator] {}

一个生成器返回的是一个迭代器。

什么是迭代器

js中,必须实现 next()方法, 且next方法返回两个属性的对象

{
    done: boolean,
    value: unknow
}
  • doneboolean 类型。true 表示迭代已完成, false 表示还有值
  • value: 当前迭代的值, 但 done 属性为 true 的时候为 undefined

迭代器的概念清楚了, 那它是用来干什么的。 顾名思义 迭代

什么是迭代

处理数据的过程, 按照约定的顺序, 从集合中逐个获取元素的操作

在开发中,经常会有迭代的场景

  • 数据遍历: 逐个访问数组中的每个元素
  • 文件读取: 逐行读取文件内容

看上去和遍历很相似, 但是存在着本质的区别

迭代 vs 遍历

特性迭代遍历
处理方式按需处理数据,灵活性更高完整处理数据,结构严谨
可否终止可以随时终止必须处理所有元素

Example - next 调用

function* g() {
  console.log('第一次执行')
  yield '第一'
  console.log('第二次执行')
  yield '第二'
}

const it = g()

console.log(it.next()) // {value: '第一', done: false}
console.log(it.next()) // {value: '第二', done: false}

console.log(it.next()) // {value: undefined, done: true}
flowchart TD
  0["g() 调用 → 得到迭代器 it<br/>函数体**没执行**"]
    1["it.next() <br/>打印:第一次执行<br/>返回:'第一'"]
    2["it.next() <br/>打印:第二次执行<br/>返回:'第二'"]
    3["it.next() <br/>返回:undefined, done:true"]

    0 --> 1 --> 2 --> 3

example-参数传递

function* paramGenerator() {
  const a = yield 1
  console.log(`第一次 next 传入: ${a}`)

  const b = yield 2
  console.log(`第二次 next 传入: ${b}`)

  return a + b
}

const gen = paramGenerator()
console.log(gen.next()) // {value: 1, done: false}
console.log(gen.next(10)) // {value: 2, done: false}, a = 10
console.log(gen.next(20)) // {value: 30, done: true}, b = 20
flowchart TD
  0["paramGenerator()<br/>得到迭代器 gen<br/>函数体未执行"]
  1["gen.next()<br/>执行到 yield <br />此时还没赋值<br/>返回 {1, false}"]
  2["gen.next(10)<br/>a = 10,打印日志<br/>执行到 yield 2<br/>返回 {2, false}"]
  3["gen.next(20)<br/>b = 20,打印日志<br/>return 30<br/>返回 {30, true}"]

  0 --> 1 --> 2 --> 3