迭代器模式

实现迭代器模式,顺序访问集合元素而不暴露内部结构

问题

实现迭代器模式,提供统一的方式遍历不同类型的集合。

解答

基本迭代器实现

// 创建一个简单的迭代器
function createIterator(items) {
  let index = 0;
  
  return {
    next() {
      if (index < items.length) {
        return { value: items[index++], done: false };
      }
      return { value: undefined, done: true };
    }
  };
}

// 使用
const iterator = createIterator([1, 2, 3]);
console.log(iterator.next()); // { value: 1, done: false }
console.log(iterator.next()); // { value: 2, done: false }
console.log(iterator.next()); // { value: 3, done: false }
console.log(iterator.next()); // { value: undefined, done: true }

实现可迭代对象

// 自定义可迭代对象,实现 Symbol.iterator
class Range {
  constructor(start, end) {
    this.start = start;
    this.end = end;
  }
  
  // 实现迭代器协议
  [Symbol.iterator]() {
    let current = this.start;
    const end = this.end;
    
    return {
      next() {
        if (current <= end) {
          return { value: current++, done: false };
        }
        return { value: undefined, done: true };
      }
    };
  }
}

// 使用 for...of 遍历
const range = new Range(1, 5);
for (const num of range) {
  console.log(num); // 1, 2, 3, 4, 5
}

// 也可以使用展开运算符
console.log([...range]); // [1, 2, 3, 4, 5]

使用 Generator 简化实现

// Generator 函数自动返回迭代器
class Collection {
  constructor() {
    this.items = [];
  }
  
  add(item) {
    this.items.push(item);
  }
  
  // 使用 Generator 实现迭代器
  *[Symbol.iterator]() {
    for (const item of this.items) {
      yield item;
    }
  }
  
  // 反向迭代器
  *reverse() {
    for (let i = this.items.length - 1; i >= 0; i--) {
      yield this.items[i];
    }
  }
}

const collection = new Collection();
collection.add('a');
collection.add('b');
collection.add('c');

// 正向遍历
for (const item of collection) {
  console.log(item); // a, b, c
}

// 反向遍历
for (const item of collection.reverse()) {
  console.log(item); // c, b, a
}

树结构迭代器

// 二叉树节点
class TreeNode {
  constructor(value, left = null, right = null) {
    this.value = value;
    this.left = left;
    this.right = right;
  }
}

// 二叉树,支持多种遍历方式
class BinaryTree {
  constructor(root) {
    this.root = root;
  }
  
  // 中序遍历(默认迭代器)
  *[Symbol.iterator]() {
    yield* this.inOrder(this.root);
  }
  
  *inOrder(node) {
    if (node) {
      yield* this.inOrder(node.left);
      yield node.value;
      yield* this.inOrder(node.right);
    }
  }
  
  // 前序遍历
  *preOrder(node = this.root) {
    if (node) {
      yield node.value;
      yield* this.preOrder(node.left);
      yield* this.preOrder(node.right);
    }
  }
  
  // 后序遍历
  *postOrder(node = this.root) {
    if (node) {
      yield* this.postOrder(node.left);
      yield* this.postOrder(node.right);
      yield node.value;
    }
  }
}

// 构建树:     1
//           / \
//          2   3
const tree = new BinaryTree(
  new TreeNode(1, new TreeNode(2), new TreeNode(3))
);

console.log([...tree]);              // [2, 1, 3] 中序
console.log([...tree.preOrder()]);   // [1, 2, 3] 前序
console.log([...tree.postOrder()]);  // [2, 3, 1] 后序

惰性迭代器

// 惰性求值,按需计算
function* lazyMap(iterable, fn) {
  for (const item of iterable) {
    yield fn(item);
  }
}

function* lazyFilter(iterable, predicate) {
  for (const item of iterable) {
    if (predicate(item)) {
      yield item;
    }
  }
}

function* lazyTake(iterable, n) {
  let count = 0;
  for (const item of iterable) {
    if (count++ >= n) break;
    yield item;
  }
}

// 链式调用,惰性求值
const numbers = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10];

const result = lazyTake(
  lazyMap(
    lazyFilter(numbers, x => x % 2 === 0),  // 筛选偶数
    x => x * 2                               // 乘以 2
  ),
  3                                          // 只取前 3 个
);

console.log([...result]); // [4, 8, 12]

关键点

  • 迭代器对象需实现 next() 方法,返回 { value, done }
  • 可迭代对象需实现 Symbol.iterator 方法,返回迭代器
  • Generator 函数是创建迭代器的简洁方式,yield 暂停执行并返回值
  • 迭代器支持 for...of、展开运算符、Array.from() 等语法
  • 惰性迭代器按需计算,适合处理大数据集或无限序列