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 的使用。