迭代器模式(Iterator)
迭代器模式是指提供一种方法顺序访问一个聚合对象中的各个元素,而又不需要暴露该对象的内部表示。
目前大多数语言都有内置的迭代器了,如 javascript
的 Array.prototype.forEach
迭代器分为两类,一种是内部迭代器,一种是外部迭代器。都有各自的使用场景。
内部迭代器
内部迭代器是内部已经编写好了迭代规则,外部不用关心迭代内部的实现,只需要一次初始的调用即可。如 js
中的 forEach
。
优点:调用简单
缺点:灵活性弱
实现一个简单的内部迭代器
每次循环都会把当前的 index
和 item
传给回调函数。
javascript
/**
* 迭代器
* @param ary {array} 数组
* @param callback 回调
*/
const each = function (ary, callback) {
for (let i = 0, l = ary.length; i < l; i++) {
callback.call(ary[i], i, ary[i]);
}
}
each([1, 2, 3], function (index, item) {
console.log(`index:${index},item:${item}`)
})
// 输出:
// index:0,item:1
// index:1,item:2
// index:2,item:3
外部迭代器
外部迭代器必须显式地请求迭代下一个元素。
优点:灵活性较强
缺点:增加了调用的复杂度
实现一个简单的外部迭代器
javascript
/**
* 迭代器
* @param obj {array} 数组
* @return {...} {object}
*/
const Iterator = function (obj) {
let current = 0
// 迭代下一个
const next = function () {
current += 1
}
// 是否完成迭代
const isDone = function () {
return current >= obj.length
}
// 获取当前的值
const getCurrItem = function () {
return obj[current]
}
return {
next,
isDone,
getCurrItem
}
}
const iterator1 = Iterator([1, 2, 3])
console.log(iterator1.isDone()) // false
console.log(iterator1.getCurrItem()) // 1
iterator1.next()
console.log(iterator1.getCurrItem()) // 2
iterator1.next()
console.log(iterator1.getCurrItem()) // 3
iterator1.next()
console.log(iterator1.isDone()) // true
在我们使用的一些库中,很多就已经实现了许多很好用的迭代器,虽然现在不用我们手写封装,但我们还是需要知道其原理。推荐一个比较好用的库 lodash
列举一下常用的迭代器原理:
- 同时支持迭代类数组和对象的迭代器 → 内部通过判断传参的类型,数组或者类数组则使用
for
循环实现,对象则使用for...in
循环实现。 - 倒序迭代器 → 内部实现循环的时候从末尾开始,即初始索引为数组长度减 1。
- 查找元素迭代器 → 内部循环数组,每次循环把值传入回调中,判断是否返回
true
或false
,然后执行return
语句中止迭代,并返回值。