迭代器模式提供一种方法按顺序访问一个聚合对象中的各个元素,而又不暴露该对象的内部表示。迭代器模式是目的性极强的模式
,它主要是用来解决遍历问题。
JS原生的集合类型数据结构,有Array(数组)和Object(对象),在ES6中,又新增了Map和Set。四种数据结构各自有着自己的内部实现,但对于使用者,我们希望以同样的一套规则去遍历它们,所以ES6在推出新数据结构的同时也推出了一套统一的接口机制——迭代器(Iterator)
。
Symbol.iterator
属性(这个属性就是Iterator的具体实现,它本质上是当前数据结构默认的迭代器生成函数),就可以被遍历
,确切的说是被for...of...循环和迭代器的next方法遍历,for...of...的背后正是对next方法的反复调用。在ES6中,针对Array、Map、Set、String、TypedArray、函数的 arguments 对象、NodeList 对象这些原生的数据结构都可以通过for...of...进行遍历。
迭代就是不断的去拿下一个值的一个过程,以及遍历完的状态,是否完成遍历。
// 定义生成器函数,入参是任意集合
function iteratorGenerator(list) {
// idx记录当前访问的索引
let idx = 0
// len记录传入集合的长度
let len = list.length
return {
// 自定义next方法
next: function() {
// 如果索引还没有超出集合长度,done为false
let done = idx >= len
// 如果done为false,则可以继续取值
let value = !done ? list[idx++] : undefined
// 将当前值与遍历是否完毕(done)返回
return {
done: done,
value: value
}
}
}
}
let iterator = iteratorGenerator(['1号选手', '2号选手', '3号选手'])
iterator.next()
iterator.next()
iterator.next()
在es6 中生成器函数
function * xxx 可以返回生成器对象( Generator 对象由生成器函数返回并且它符合可迭代协议和迭代器协议。)
生成器函数在执行时能暂停,后面又能从暂停处继续执行。
// 生成器函数写法
function* iteratorGenerator1(list) {
yield '生成器函数,我是1号'
yield '生成器函数,我是2号'
yield '生成器函数,我是3号'
}
let iterator1 = iteratorGenerator1()
console.log(iterator1.next())
console.log(iterator1.next())
console.log(iterator1.next())
// 生成器函数写法--优化
function* iteratorGenerator2(list) {
let index = 0, len = list.length;
while (index <= len - 1) {
yield list[index]
index++
}
}
let iterator2 = iteratorGenerator2(['生成器函数优化,我是1号', '生成器函数优化,我是2号', '生成器函数优化,我说3号'])
console.log(iterator2.next())
console.log(iterator2.next())
console.log(iterator2.next())
可迭代协议:具备Symbol.iterator
迭代器协议:一个类似这个结构的对象:
{
next: function () {
return {
value: 'xx', // 当前遍历节点的值
done: false // 是否完成遍历
}
}
}
参考迭代协议
迭代器模式是一种行为型设计模式,它允许客户端逐个访问一个聚合对象中的元素,而不暴露该对象的内部表示。迭代器模式提供了一种统一的方式来遍历不同类型的集合,使客户端代码更加简洁和可复用。
行为型模式的关注点在于对象之间的通信和职责分配(描述结构模型中对象的动态特征)。行为型模式关注的是对象之间的交云和协作,即它们是如何相互作用的,以及如何分配职责和算法来完成任务。