深入理解 JS 异步编程 02(迭代器与可迭代对象篇)

Iterator 与 Iterable

迭代器(Iterator)

  • 迭代器是一个对象,它提供了一种方法来顺序访问一个集合(或称为“序列”)中的元素,且使用该接口时无需关心对象内部实现的细节 → 即: 帮助我们对某个数据结构进行遍历的对象

  • 在 JavaScript 中,迭代器也是一个具体的对象,该对象需要符合迭代器的协议(iterator protocol) → 在 JavaScript 这个标准就是需要由一个特定的 next 方法(↓)

  • next 方法的要求: 该方法返回一个对象,该对象包含如下两个属性

    • value: 表示某个序列中的下一个值
    • done: 一个 boolean 值,表示是否已经完成了所有遍历
  • 代码示例

    • 基本使用

      • const arr = [1, 2, 3]
        
        let index = 0
        const arrIterator = {
            next() { // -- 特定的 next 方法
                if (index < arr.length) return { value: arr[index++], done: false }
                else return { value: undefined, done: true }
            }
        }
        
      • + TEST
        console.log(arrIterator.next()) // { value: 1, done: false }
        console.log(arrIterator.next()) // { value: 2, done: false }
        console.log(arrIterator.next()) // { value: 3, done: false }
        console.log(arrIterator.next()) // { value: undefined, done: true }
        console.log(arrIterator.next()) // { value: undefined, done: true }
        
    • 生成数组迭代器的方法封装(练习)

      • + 方法封装
        function createArrayIterator(arr) {
            let [index, len] = [0, arr.length]
            return { // -- 返回对应 arr 数组的迭代器对象
                next() {
                    if (index < len) return { value: arr[index++], done: false }
                    else return { value: undefined, done: true }
                }
            }
        }
        
      • + TEST
        const arr = [1, 2, 3]
        const arrIterator = createArrayIterator(arr) // -- 创建 arr 数组的迭代器对象
        
        console.log(arrIterator.next()) // { value: 1, done: false }
        console.log(arrIterator.next()) // { value: 2, done: false }
        console.log(arrIterator.next()) // { value: 3, done: false }
        console.log(arrIterator.next()) // { value: undefined, done: true }
        console.log(arrIterator.next()) // { value: undefined, done: true }
        

可迭代对象(Iterable)

  • **可迭代对象是指那些内置了 Symbol.iterator 方法的对象 → 当一个对象是一个可迭代对象时,我们就可以对其进行某些迭代操作(如 for … of 操作等) **

  • 任何具有Symbol.iterator方法的对象都被认为是可迭代的(该方法需要返回一个迭代器对象)

  • 如: 我们可以通过一个类数组的例子来进行示例

    • + 1. 引入: 通常一个数组我们是可以直接通过扩展运算符(...),将一个数组中的元素浅拷贝到另一个数组中的
      const arr = [1, 2, 3, 4]
      console.log([...arr]) // [1, 2, 3, 4]
      
    • + 2. 但如果是一个类数组呐(类数组: 具有索引和值 & 具有 length 属性)
      const likeArray = { 
          0: 1,
          1: 2,
          2: 3,
          length: 3
      }
      
      // 报错: 对于数组来说,它们内置支持迭代器协议,因此可以直接使用扩展运算符来展开数组的元素 / 但对应该类数组来说,并没有实现对应的迭代器协议
      console.log([...likeArray]) // TypeError: likeArray is not iterable
      
    • + 3. 我们可以通过给该 likeArray 数组,添加一个 Symbol.iterator 方法,来使其变成可迭代对象 → 可以像数组那样也使用扩展运算符
      const likeArray = { // 类数组: 具有索引和值 & 具有 length 属性
          0: 1,
          1: 2,
          2: 3,
          length: 3,
          [Symbol.iterator]() { // -- 定义特定的 Symbol.iterator 方法,使其变成一个可迭代对象
              let idx = 0
              return { // -- Symbol.iterator 方法需要返回一个迭代器对象
                  next: () => { // -- tip: 该 next 方法需要使用箭头函数,因为需要拿到上层作用域的 this 指向,即 likeArray 执行上下文(当然也可以在 Symbol.iterator 中提前见 this 通过变量存储起来)
                      if (idx < this.length) return { value: this[idx++], done: false }
                      else return { value: undefined, done: true }
                  }
              }
          }
      }
      
      // 此时,我们再通过扩展运算符来浅拷贝 likeArray 是,就可以正常展开了
      console.log([...likeArray]) // [1, 2, 3, 4]
      
  • 原生的可迭代对象:

    • ArrayMapSetStringTypedArrayNodeList对象等都是可迭代的

    • + 我们可以通过可迭代对象中的 Symbol.iterator 方法获取对应的迭代器
      const arr = [1, 2, 3]
      
      // -- 🔺因为数组本身就是一个可迭代对象,所以其内部肯定会有 Symbol.iterator 方法
      const it = arr[Symbol.iterator]() // -- 我们可以直接执行数组中的 Symbol.iterator,来获取对应的迭代器对象
      
      console.log(it.next()) // { value: 1, done: false }
      console.log(it.next()) // { value: 2, done: false }
      console.log(it.next()) // { value: 3, done: false }
      console.log(it.next()) // { value: undefined, done: true }
      
  • 常见场景

    • 遍历集合:使用for...of循环遍历数组、字符串、Map、Set等集合
    • 生成器函数:生成器函数(function*)自动成为可迭代对象,并返回一个迭代器,用于按需生成序列中的值
    • 自定义迭代逻辑:通过实现Symbol.iterator方法,可以为自定义对象添加迭代能力,使其能够使用for...of循环遍历
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值