Skip to content

迭代器模式(Iterator)

迭代器模式是指提供一种方法顺序访问一个聚合对象中的各个元素,而又不需要暴露该对象的内部表示。

目前大多数语言都有内置的迭代器了,如 javascriptArray.prototype.forEach

迭代器分为两类,一种是内部迭代器,一种是外部迭代器。都有各自的使用场景。


内部迭代器

内部迭代器是内部已经编写好了迭代规则,外部不用关心迭代内部的实现,只需要一次初始的调用即可。如 js 中的 forEach

优点:调用简单

缺点:灵活性弱

实现一个简单的内部迭代器

每次循环都会把当前的 indexitem 传给回调函数。

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。
  • 查找元素迭代器 → 内部循环数组,每次循环把值传入回调中,判断是否返回 truefalse,然后执行 return 语句中止迭代,并返回值。

Released under the MIT License.