关于迭代器模式我所知道的

91 阅读2分钟

迭代器是用来遍历容器的,一个完整的迭代器模式一般会涉及容器和容器迭代器两部分内容。

现在流行的大部分语言都已经有了内置的迭代器实现。本质其实就是循环访问聚合对象中的各个元素。

迭代器可以分为内部迭代器和外部迭代器。

内部迭代器

内部已经定义好了迭代规则,它完全接手整个迭代过程,外部只需要一次初始调用。

外部迭代器

外部迭代器必须显式地请求迭代下一个元素。

外部迭代器虽然调用方式相对复杂,但它的适用面更广,也能满足更多变的需求。比如常见的 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
})