前端常用的7大设计模式- 迭代器模式

76 阅读2分钟

概念

迭代器模式(Iterator Pattern)是一种行为型设计模式,提供一种方法顺序访问一个聚合对象(如集合、列表、树等)中的各个元素,而又不需要暴露该对象的内部表示。它的核心目的是将遍历逻辑与数据集合解耦,使得遍历算法可以独立于集合结构变化。

核心要素

迭代器接口(Iterator Interface) 定义遍历元素所需的通用方法,如 next()hasNext()current() 等。

可迭代对象(Iterable Collection) 提供创建迭代器的方法(如 createIterator() 或 ES6 的 Symbol.iterator)。

具体迭代器(Concrete Iterator) 实现迭代器接口,保存遍历过程中的状态(如当前位置)。

前端中的迭代协议 ES6 引入的 Symbol.iterator 和迭代器协议({ value, done }),原生支持迭代器模式。


使用场景

  1. 需要统一遍历不同数据结构(数组、树、链表等)。
  2. 需要对集合进行多种遍历方式(如正序、逆序、过滤)。
  3. .......

如何实现一个简单的迭代器模式呢

简单的迭代器

// 可迭代对象
class SocialFeed {
  constructor() {
    this.posts = [];
    this.ads = [];
  }

  addPost(post) {
    this.posts.push(post);
  }

  addAd(ad) {
    this.ads.push(ad);
  }

  // 实现 Symbol.iterator 定义迭代行为
  [Symbol.iterator]() {
    let index = 0;
    const merged = [...this.posts, ...this.ads];
    return {
      next: () => {
        return index < merged.length 
          ? { value: merged[index++], done: false }
          : { done: true };
      }
    };
  }
}

// 使用迭代器
const feed = new SocialFeed();
feed.addPost("Post 1");
feed.addAd("Ad 1");
for (const item of feed) {
  console.log(item); // 输出 "Post 1", "Ad 1"
}

树形结构迭代器

class TreeNode {
  constructor(value, children = []) {
    this.value = value;
    this.children = children;
  }

  // 深度优先遍历迭代器
  *[Symbol.iterator]() {
    yield this.value;
    for (const child of this.children) {
      yield* child;
    }
  }
}

// 使用生成器函数实现遍历
const tree = new TreeNode("Root", [
  new TreeNode("Child 1", [new TreeNode("Grandchild 1")]),
  new TreeNode("Child 2")
]);

for (const node of tree) {
  console.log(node); // 输出 "Root", "Child 1", "Grandchild 1", "Child 2"
}

优缺点

优点

  1. 解耦遍历逻辑与集合结构,支持多种遍历方式。
  2. 简化客户端代码,只需调用统一接口。
  3. 遵循单一职责原则和开闭原则。

缺点

  1. 对简单集合(如数组)使用迭代器可能带来不必要的复杂性。
  2. 某些场景下(如直接访问元素)性能不如直接遍历。

总结

迭代器模式在前端开发中广泛应用于处理集合遍历、惰性加载和复杂数据结构(如树、图)的场景。随着 ES6 迭代协议的普及,现代 JavaScript 可以更优雅地实现这一模式(如生成器函数和 for...of)。在需要统一遍历逻辑或隐藏集合内部细节时,优先选择迭代器模式;但对于简单数组遍历,直接使用 forEachfor 循环可能更高效。