迭代器是用来遍历容器的,一个完整的迭代器模式一般会涉及容器和容器迭代器两部分内容。
现在流行的大部分语言都已经有了内置的迭代器实现。本质其实就是循环访问聚合对象中的各个元素。
迭代器可以分为内部迭代器和外部迭代器。
内部迭代器
内部已经定义好了迭代规则,它完全接手整个迭代过程,外部只需要一次初始调用
外部迭代器
外部迭代器必须显式地请求迭代下一个元素。
外部迭代器虽然调用方式相对复杂,但它的适用面更广,也能满足更多变的需求。比如常见的 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 })