JS迭代器

JS迭代器

迭代器(iterator)在目前主流的编程语言中都是一个重要的概念,用来遍历集合的接口,迭代器通过提供统一的接口来访问集合中的元素。在 JS 中,使用迭代器可以方便地遍历集合,比如数组、对象、类等各种数据结构。

迭代器接口

迭代器接口是一种具有特殊结构的对象实现了迭代器协议,返回next方法,该方法返回的对象具有value和done两个属性,分别表示当前迭代器对象的值和是否迭代结束。

常见的默认包含迭代器的数据结构有:Array、Map、Set、String、TypedArray、Generator。

这些数据有一个共同的特点,可以通过 Symbol.iterator 属性,返回当前数据结构的迭代器对象。

迭代器的访问当时主要有以下几种:

  • 遍历next方法
js 复制代码
const arr = [1, 2, 3, 4, 5]
const iterator = arr[Symbol.iterator]()
let item = iterator.next()

while (!item.done) {
  console.log(item.value)
}
  • for...of 循环

可以理解为遍历 next 方法的语法糖。

js 复制代码
const arr = [1, 2, 3, 4, 5]
for (const item of arr) {
  console.log(item)
}
  • 数组拓展运算符
js 复制代码
function* generator() {
  yield 1
  yield 2
  yield 3
}

const gen = generator()
console.log([...gen]) // [1, 2, 3]
  • 数组解构
js 复制代码
const [a, b, c] = new Set([1, 2, 3])
console.log(a, b, c) // 1 2 3

自定义迭代器

Object 对象默认是不能被迭代,但是可以通过 Symbol.iterator 属性来实现自定义迭代器。

js 复制代码
const obj = {
  data: [1, 2, 3, 4],
  [Symbol.iterator]() {
    let index = 0
    return {
      next: () => {
        if (index < this.data.length) {
          return { value: this.data[index++], done: false }
        } else {
          return { value: undefined, done: true }
        }
      },
    }
  },
}

for (const item of obj) {
  console.log(item) // 1 2 3 4
}
console.log([...obj]) // [1, 2, 3, 4]

另外在浏览器中一些对象也实现了迭代器接口,比如 DOM 对象中的CSSStyleDeclaration, 我们可以利用实现的迭代器从而转换为 Array 从而使用一些内置的遍历方法简化处理。

js 复制代码
;[...getComputedStyle(document.body)].filter((val) => {
  return val.startsWith('background')
})

接收迭代器对象的 API

许多 API 默认接收迭代器对象,比如 Map 、Set、 Promise.all、Array.from 等。

js 复制代码
const obj = {}

new Set(
  (function* () {
    yield {}
    yield myObj
    yield {}
  })()
).has(obj) // true

异步迭代器

异步迭代器是基于于异步迭代协议,与迭代器协议基本类似,只是调用迭代器方法的返回值包装在 Promise 中。

当对象实现 Symbol.asyncIterator 属性,便可以通过异步迭代器进行访问。

js 复制代码
const obj = {
  data: [1, 2, 3, 4],
  [Symbol.asyncIterator]() {
    let index = 0
    return {
      next: () => {
        if (index < this.data.length) {
          return Promise.resolve({ value: this.data[index++], done: false })
        } else {
          return Promise.resolve({ value: undefined, done: true })
        }
      },
    }
  },
}

;(async () => {
  for await (const item of obj) {
    console.log(item) // 1 2 3 4
  }
})()

总结

迭代器在JS中是一种常见的底层机制,通过这个机制可以方便的遍历数据结构.了解迭代器的使用,可以更好的理解 JS 的一些底层机制以及一些常用 API 的使用。

相关推荐
ss2733 分钟前
AI全栈实战 | 2.2-02 React 思维模型:数据不可变 vs Vue 数据可变,两种哲学把复杂度推给谁
前端·vue.js·react.js
天衍四九-7 分钟前
Docker Compose企业实战系列(三):Vue/React前端项目容器化完整部署
前端·vue.js·docker
Rosanci21 分钟前
从零到合入主线:我的 DeepSeek Harness 开源贡献实战手记
开发语言·前端·开源
用户9608198422329 分钟前
多周期联看时十字光标对不齐:前端排查「时间桶」的三步清单
前端
Data analyse4561 小时前
数据合规的敏感数据怎么识别?
前端·人工智能·数据分析
陪我一起学编程1 小时前
vue3笔记
前端·webpack·vue3·vite·脚手架·vue3笔记·组件式
object not found2 小时前
WooCommerce 接入 KPay 后订单完成页不显示订单信息:returnUrl 动态参数问题解决
前端·wordpress·独立站支付
yume_sibai2 小时前
04-Nginx部署实战完全指南(前端部署 + 后端代理 + 监控告警 + 故障排查)
运维·前端·nginx
data analyse 4562 小时前
数据合规的同意记录怎么留存?
前端·人工智能·数据分析
linux_cfan2 小时前
videojs v10 源代码系列解读:35 · HLS 解析器:multivariant 与 media playlist
前端·javascript·音视频