实现一个迭代器生成函数

手写实现一个可以生成迭代器的函数,支持自定义迭代逻辑,理解 JavaScript 迭代器协议

问题

在 JavaScript 中,迭代器(Iterator)是一种设计模式,它提供了一种统一的方式来遍历各种数据结构。本题要求实现一个迭代器生成函数,使得对象可以被 for...of 循环遍历,并理解迭代器协议的原理。

解答

/**
 * 创建一个范围迭代器
 * @param {number} start - 起始值
 * @param {number} end - 结束值
 * @param {number} step - 步长,默认为1
 * @returns {Object} 迭代器对象
 */
function createRangeIterator(start, end, step = 1) {
  let current = start;
  
  return {
    // 实现迭代器协议:必须有 next 方法
    next() {
      if (current < end) {
        const value = current;
        current += step;
        return { value, done: false };
      }
      return { value: undefined, done: true };
    },
    
    // 实现可迭代协议:返回迭代器自身
    [Symbol.iterator]() {
      return this;
    }
  };
}

/**
 * 创建一个可迭代对象
 * @param {Array} data - 数据数组
 * @returns {Object} 可迭代对象
 */
function createIterableObject(data) {
  return {
    [Symbol.iterator]() {
      let index = 0;
      
      return {
        next() {
          if (index < data.length) {
            return { value: data[index++], done: false };
          }
          return { value: undefined, done: true };
        }
      };
    }
  };
}

/**
 * 使用生成器函数实现迭代器(推荐方式)
 * @param {number} start - 起始值
 * @param {number} end - 结束值
 * @param {number} step - 步长
 */
function* rangeGenerator(start, end, step = 1) {
  for (let i = start; i < end; i += step) {
    yield i;
  }
}

/**
 * 创建一个无限迭代器
 */
function createInfiniteIterator() {
  let count = 0;
  
  return {
    next() {
      return { value: count++, done: false };
    },
    [Symbol.iterator]() {
      return this;
    }
  };
}

使用示例

// 示例1:使用范围迭代器
const rangeIter = createRangeIterator(0, 5);
for (const num of rangeIter) {
  console.log(num); // 输出: 0, 1, 2, 3, 4
}

// 示例2:手动调用 next 方法
const iter = createRangeIterator(10, 13);
console.log(iter.next()); // { value: 10, done: false }
console.log(iter.next()); // { value: 11, done: false }
console.log(iter.next()); // { value: 12, done: false }
console.log(iter.next()); // { value: undefined, done: true }

// 示例3:使用可迭代对象
const iterableObj = createIterableObject(['a', 'b', 'c']);
for (const item of iterableObj) {
  console.log(item); // 输出: a, b, c
}

// 示例4:使用生成器函数
const generator = rangeGenerator(0, 5, 2);
console.log([...generator]); // [0, 2, 4]

// 示例5:解构赋值
const [first, second, ...rest] = createRangeIterator(1, 6);
console.log(first, second, rest); // 1 2 [3, 4, 5]

// 示例6:无限迭代器(需要手动控制)
const infiniteIter = createInfiniteIterator();
console.log(infiniteIter.next().value); // 0
console.log(infiniteIter.next().value); // 1
console.log(infiniteIter.next().value); // 2

// 示例7:结合数组方法
const rangeArray = Array.from(createRangeIterator(1, 6));
console.log(rangeArray); // [1, 2, 3, 4, 5]

关键点

  • 迭代器协议:对象必须实现 next() 方法,返回包含 valuedone 属性的对象

    • value:当前迭代的值
    • done:布尔值,表示迭代是否完成
  • 可迭代协议:对象必须实现 [Symbol.iterator] 方法,返回一个迭代器对象

  • 生成器函数:使用 function*yield 关键字是创建迭代器的最简洁方式,自动实现迭代器协议

  • 状态管理:迭代器需要维护内部状态(如当前索引、计数器等),每次调用 next() 时更新状态

  • 惰性求值:迭代器按需生成值,不会一次性计算所有结果,适合处理大数据集或无限序列

  • 一次性消费:大多数迭代器只能遍历一次,再次遍历需要重新创建(除非实现了可重置逻辑)

  • 应用场景:自定义数据结构遍历、分页数据加载、流式数据处理、惰性计算等