1.介绍
普通for循环不是迭代器
const arr = [10, 20, 30]
const length = arr.length
for (let i = 0; i < length; i++) {
console.log(arr[i]);
}
简易迭代器:
const pList = document.querySelectorAll('p')
pList.forEach(p=>console.log(p))
2.小结
- 顺序访问有序结构(如数组、NodeList)
- 不知道数据的长度和内部结构
- 高内聚,低耦合
3.迭代器模式代码演示
class DataIterator{
private data: number[]
private index: number = 0
constructor(container: DataContainer) {
this.data = container.data
}
next () {
if (this.hasNext()) {
return this.data[this.index++]
}
return null
}
hasNext () {
if (this.index >= this.data.length) {
return false
}
return true
}
}
class DataContainer{
data = [10, 20, 30, 40, 50]
getIterator (): DataIterator {
return new DataIterator(this)
}
}
const container = new DataContainer()
const iterator = container.getIterator()
while(iterator.hasNext()) {
console.log(iterator.next());
}
4.是否符合设计原则
- 使用者和目标分离,解耦
- 目标能自行控制其内部逻辑
- 使用者不关心目标的内部结构
5.迭代器模式-使用场景
- 有序结构
- Symbol.iterator和迭代器
- 迭代器的应用
1.有序结构
- 字符串
- 数组
- Map
- Set
- NodeList等DOM集合
- arguments
2.Symbol.iterator
自定义迭代器:
interface IteratorRes {
value: number | undefined
done: boolean
}
class CustomIterator{
private length = 3
private index = 0
next (): IteratorRes{
this.index++
if (this.index <= this.length) {
return {value: this.index, done: false}
}
return {value: undefined, done: true}
}
[Symbol.iterator] () {
return this
}
}
const iterator = new CustomIterator()
console.log(iterator.next())
console.log(iterator.next())
console.log(iterator.next())
console.log(iterator.next())
迭代器的作用
- 用于for...of
- 数组:解构、扩展操作符、Array.from
- 用于创建Map和Set
- 用于Promise.all和Promise.race
- 用于 yield *
Generator 生成器
- 基本使用
- yield * 语法
- yield 遍历DOM树
function* genNums () {
// yield 1
// yield 2
// yield 3
yield* [1, 2, 3]
}
//生成器函数返回的是迭代器,如 arr[Symbol.iterator]()
const numsIterator = genNums()
//console.log(numsIterator.next()) //{value: 1, done: false}
//console.log(numsIterator.next()) //{value: 2, done: false}
//console.log(numsIterator.next()) //{value: 3, done: false}
//console.log(numsIterator.next()) //{value: undefined, done: true}
for(let n of numsIterator) {
console.log(n) // 1,2,3
}
class CustomIterator {
private data: number[]
constructor() {
this.data = [100, 200, 300]
}
* [Symbol.iterator]() {
yield* this.data
}
}
const iterator = new CustomIterator()
for (let n of iterator) {
console.log(n)
}
使用Generator 遍历DOM树
function* traverse (elemList: Element[]): any {
for (const elem of elemList) {
yield elem
}
const children = Array.from(elemList.children)
if(children.length) {
yield* traverse(children)
}
}
const container = document.querySelector('#container')
if(container) {
const iterator = traverse([container])
for(let elem of iterator) {
console.log(elem)
}
}
注意事项
- Object 不是有序结构
- 简单的for循环不是迭代器,迭代器是解决for循环的问题