迭代器是用来遍历容器的,一个完整的迭代器模式一般会涉及容器和容器迭代器两部分内容。
现在流行的大部分语言都已经有了内置的迭代器实现。本质其实就是循环访问聚合对象中的各个元素。
迭代器可以分为内部迭代器和外部迭代器。
内部迭代器
内部已经定义好了迭代规则,它完全接手整个迭代过程,外部只需要一次初始调用。
外部迭代器
外部迭代器必须显式地请求迭代下一个元素。
外部迭代器虽然调用方式相对复杂,但它的适用面更广,也能满足更多变的需求。比如常见的 next()、nextTick() 等。
// jq 迭代器
$.each([1, 2, 3], (i, n) => console.log('当前下标为: ' + i, '当前值为:' + n));
// 简单实现内部迭代器
const each = (arr, cb) => {
arr.forEach((item, index) => cb.call(item, index, item))
}
each([1, 2, 3], (i, n) => console.log([i, n]));
// 简单应用
const compare = (arr1, arr2) => {
if (arr1.length !== arr2.length) {
return false;
}
let r = true;
each(arr1, (i, n) => {
if (n !== arr2[i]) {
r = false
}
})
return r
}
// 简单实现外部迭代器
class Iterator {
constructor(obj) {
this.current = 0;
this.obj = obj;
this.length = obj.length;
}
next() {
this.current += 1;
}
isDone() {
return this.current >= this.obj.length;
}
getCurItem() {
return this.obj[this.current];
}
}
const compare = (iterator1, iterator2) => {
if (iterator1.length !== iterator2.length) {
console.log('iterator1和iterator2不相等');
}
while (!iterator1.isDone() && !iterator2.isDone()) {
if (iterator1.getCurItem() !== iterator2.getCurItem()) {
console.log('iterator1和iterator2不相等')
return false
}
iterator1.next();
iterator2.next();
}
alert('iterator1和iterator2相等');
}
const iterator1 = new Iterator([1,2,3,4])
const iterator2 = new Iterator([1,2,4,4])
compare(iterator1, iterator2)
内部迭代器和外部迭代器在实际生产中没有优劣之分,究竟使用哪个要根据需求场景而定。
拓展应用 倒序迭代器 中止迭代器
// 倒序迭代器
const reverseEach = (arr, cb) => {
for (let i = arr.length - 1; i >= 0; i--) {
cb(i, arr[i]);
}
}
reverseEach([1, 2, 3], (i, n) => console.log(n))
// 中止迭代器 回调函数中包含循环的终止条件
const Each = (arr, cb) => {
for (let i = 0; i < arr.length; i++) {
if (cb(i, arr[i]) === false) {
break
}
}
}
Each([1, 2, 3, 4, 5], (i, n) => {
if (n > 3) { // 中止条件
return false
}
console.log(n) // 1,2,3
})