意图:
提供一种方法顺序访问一个聚合对象中各个元素, 而又无须暴露该对象的内部表示(被遍历对象的长度,内部数据结构,元素下标等)。
主要解决:
不同的方式来遍历整个整合对象。
何时使用:
遍历一个聚合对象。用于顺序访问集合对象的元素,不需要知道集合对象的底层表示。
如何解决:
把在元素之间游走的责任交给迭代器,而不是聚合对象。
关键代码:
定义接口:hasNext, next。
前端中的迭代器模式
1.for 循环不是迭代器
因为通过for循环遍历顺序结构对象需要知道被遍历对象的长度,索引下标才能完成对顺序结构对象的遍历。
2.forEach 是最简易的迭代器
不需要知道被遍历对象的长度,内部数据结构,对应下标索引就可以遍历出该对象的值。
TS代码演示一个基础的迭代器 (核心:next 和 hasNext 方法)
class DataIterator {
private data: number[]
// 当前访问到第几个元素了 (当前访问元素的下标)
private index = 0
constructor(container: DataContainer) {
this.data = container.data
}
// 返回当前下标元素的值
next(): number | null {
if (this.hasNext()) {
// 返回当前下标元素的值 并且 累加 index
return this.data[this.index++]
}
return null
}
// 判断当前元素的下一个元素是否有值
hasNext() {
if (this.index >= this.data.length) return false
return true
}
}
class DataContainer {
data: number[] = [10, 20, 30, 40]
getIterator() {
return new DataIterator(this)
}
}
const container = new DataContainer()
const iterator = container.getIterator()
while(iterator.hasNext()) {
const num = iterator.next()
console.log(num)
}
// 不用在外部获取当前遍历数组的 length 也不用for循环
3.JS迭代器的场景
JS 有序对象,都内置迭代器
- 字符串
- 数组
- NodeList 等 DOM 集合
- Map
- Set
- arguments
【注意】对象 object 不是有序结构
4.内置迭代器:Symbol.iterator
每个有序对象,都内置了 `Symbol.iterator` 属性,属性值是一个函数。
执行该函数讲返回 iterator 迭代器,有 `next()` 方法,执行返回 `{ value, done }` 结构。
// 拿数组举例,其他类型也一样
const arr = [10, 20, 30]
const iterator = arr[Symbol.iterator]()
iterator.next() // {value: 10, done: false}
iterator.next() // {value: 20, done: false}
iterator.next() // {value: 30, done: false}
iterator.next() // {value: undefined, done: true}
// 另外,有些对象的 API 也会生成有序对象
const map = new Map([ ['k1', 'v1'], ['k2', 'v2'] ])
const mapIterator = map[Symbol.iterator]()
const values = map.values() // 并不是 Array
const valuesIterator = values[Symbol.iterator]()
5.for of 与 迭代器之间的联系
for of 可以遍历包含迭代器的有序对象,包含自定义迭代器
for of 不断返回 调用迭代器中 next 方法 返回值 中的 value 值
6.有序对象(内置迭代器)可以进行的操作
for of 遍历
扩展运算符
解构赋值
Array.form