概念
迭代器模式(Iterator Pattern)是一种行为型设计模式,提供一种方法顺序访问一个聚合对象(如集合、列表、树等)中的各个元素,而又不需要暴露该对象的内部表示。它的核心目的是将遍历逻辑与数据集合解耦,使得遍历算法可以独立于集合结构变化。
核心要素
迭代器接口(Iterator Interface) 定义遍历元素所需的通用方法,如
next()、hasNext()、current()等。可迭代对象(Iterable Collection) 提供创建迭代器的方法(如
createIterator()或 ES6 的Symbol.iterator)。具体迭代器(Concrete Iterator) 实现迭代器接口,保存遍历过程中的状态(如当前位置)。
前端中的迭代协议 ES6 引入的
Symbol.iterator和迭代器协议({ value, done }),原生支持迭代器模式。
使用场景
- 需要统一遍历不同数据结构(数组、树、链表等)。
- 需要对集合进行多种遍历方式(如正序、逆序、过滤)。
- .......
如何实现一个简单的迭代器模式呢
简单的迭代器
// 可迭代对象
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"
}
优缺点
优点
- 解耦遍历逻辑与集合结构,支持多种遍历方式。
- 简化客户端代码,只需调用统一接口。
- 遵循单一职责原则和开闭原则。
缺点
- 对简单集合(如数组)使用迭代器可能带来不必要的复杂性。
- 某些场景下(如直接访问元素)性能不如直接遍历。
总结
迭代器模式在前端开发中广泛应用于处理集合遍历、惰性加载和复杂数据结构(如树、图)的场景。随着 ES6 迭代协议的普及,现代 JavaScript 可以更优雅地实现这一模式(如生成器函数和 for...of)。在需要统一遍历逻辑或隐藏集合内部细节时,优先选择迭代器模式;但对于简单数组遍历,直接使用 forEach 或 for 循环可能更高效。