JS基础 之 迭代器和生成器

254 阅读2分钟

迭代器

1、什么是可迭代对象

  • A对象或者A对象的原型实现了@@iterator方法,这个方法返回一个迭代器,可以通过Symbol.iterator访问

2、什么是迭代器

  • @@iterator方法return的内容就是迭代器。实际上就是一个有 next 方法的对象。

3、什么是next方法

  • next方法返回格式:{done: Boolean, value: any},当 done=true 时,表示迭代结束。

4、可迭代对象和迭代器的应用

  • for item of A [...A] Array.from(A)等等使用的前提——“A”是一个可迭代对象。
  • 比如for of遍历,它启动时会调用Symbol.iterator方法(没找到就报错), 该方法返回一个迭代器(一个有 next 方法的对象),for of的循环实际上就是不停地在调用next()
  • Array、Map等本身就内置了Symbol.iterator方法,所以本身就是可迭代对象。自定义的对象没有Symbol.iterator方法,如果要参与for of循环,就得自定义Symbol.iterator方法。

5、加速理解:自定义一个可迭代对象

let obj = {
  a: 'aa',
  b: 'bb',
  c: 'cc'
}

obj[Symbol.iterator] = function () {
  const _this = this // 方便获取obj
  return {
    currentIdx: 0,
    next: function() {
      const totalLength = Object.keys(_this).length // ['a', 'b', 'c'].length
      const values = Object.values(_this) // ['aa', 'bb', 'cc']
      if(this.currentIdx < totalLength) {
        return {done: false, value: values[this.currentIdx++]}
      } else {
        return {done: true}
      }
    }
  }
}

// for of 遍历
for (let i of obj) { // 实际上就是在不停调用next,直至{ done: true }
  console.log('i :>> ', i)
}
// 输出
// i :>>  aa
// i :>>  bb
// i :>>  cc


// for of 遍历拆解
const iterator = obj[Symbol.iterator]()

console.log('test :>> ', iterator.next()) // { done: false, value: 'aa' }
console.log('test :>> ', iterator.next()) // { done: false, value: 'bb' }
console.log('test :>> ', iterator.next()) // { done: false, value: 'cc' }
console.log('test :>> ', iterator.next()) // { done: true }
console.log('test :>> ', iterator.next()) // { done: true }

生成器

1、什么是生成器

  • 生成器(Generator Object):指生成器对象,生成器函数返回的东西,即Generator对象
  • 生成器既是一个迭代器 —— 有next方法的对象,又是一个可迭代对象 —— 有Symbol.iterator方法的对象
  • 个人理解:生成器对象是一个特殊的可迭代对象,类似于可迭代对象的改进版,然后给改进版换了个新名字,类似扫把和扫地机器人的区别~

2、什么是生成器函数

  • 生成器函数(Generator Function):指function*定义的函数(),它返回一个Generator对象

3、加速理解:改写可迭代对象

  • 每次yield类似原先return {done: false, value: this[key]}的操作
  • ⚠️调用function*的时候并不会执行函数,如下obj[Symbol.iterator]()的时候console.log(1)并不会执行,可以仔细对比一下迭代器的实现~
// 上述迭代器可以改写为
obj[Symbol.iterator] = function*() {
  for(let i = 0; i < Object.keys(this).length; i++) {
    const key = Object.keys(this)[i]
    console.log(1)
    yield this[key] // yield: 用来暂停和恢复一个生成器函数
  } 
}

// 此时 obj[Symbol.iterator]() 返回的是一个generator

4、Generator Object 应用

之前一直以为Promise是Generator的改进,应该是哪里混乱了,应该是下述这样

  • Generator 是 Iterator的改进
  • async/await 是 Generator + Promise 的语法糖~

参考链接