Skip to main content

迭代器模式 Iterator Pattern

介绍

  • 按顺序访问一个集合
  • 使用者无需知道集合的内部结构(封装)

示例

classDiagram
Container --> Iterator
class Container {
+ list: Array
+getIterator() Iterator
}

class Iterator {
+ list: Array
- index: int
+next() int
+hasNext() boolean
}
class Container {
constructor(list) {
this.list = list;
}

getIterator() {
return new Iterator(this)
}
}
class Iterator {
constructor(container) {
this.list = container.list
this.index = 0
}

hasNext() {
return this.list[this.index]
}

next() {
if (!this.hasNext()) {
return null
}
return this.list[this.index++]
}
}

const arr = [1, 2, 3, 4, 5]
const container = new Container(arr)
const iterator = container.getIterator()
while(iterator.hasNext()) {
console.log(iterator.next())
}

应用场景

each 处理可迭代对象

<div id="wrapper">
<a href="#">a1</a>
<a href="#">a2</a>
<a href="#">a3</a>
<a href="#">a4</a>
<a href="#">a5</a>
</div>
<script>
const arr = [1, 2, 3]
// 类数组
const nodeList = document.getElementsByTagName('a')

arr.forEach(x => {
console.log(x)
})

// 类数组遍历不能用 forEach
for(let i = 0; i < nodeList.length; i += 1) {
console.log(nodeList[i])
}

// 都转成数组
function each(val) {
Array.from(val).forEach((k, v) => {
console.log(k, v)
})
}
</script>

ES6 Iterator

有序数据集合类型

  • Array
  • Map
  • Set
  • String
  • TypedArray 类型化数组
  • arguments 函数参数
  • NodeList 类数组

有序数据集合特点

  • 都有 [Symbol.iterator] 属性
  • 属性值是函数,执行函数返回一个迭代器
  • 迭代器有 next 方法可顺序迭代子元素
  • 可运行 Array.prototype[Symbol.iterator] 进行测试

实践

function each(data) {
const iterator = data[Symbol.iterator]()

let item = {done: false}
while(!item.done) {
item = iterator.next()
if (!item.done) {
console.log(item.value)
}
}
}

设计原则验证

  • 迭代器对象和目标对象分离
  • 迭代器将使用者和目标对象隔离开
  • 符合开放封闭原则