JS如何实现迭代协议?可迭代对象

兄弟姐妹们在线教下,JS如何实现迭代协议?可迭代对象
最新回答
冰河铺子

2026-10-22 00:33:12

JavaScript通过实现[Symbol.iterator]方法和生成器函数(function*)来支持迭代协议,使对象可被for...of循环或展开运算符遍历。以下是具体实现方式及核心机制:

一、手动实现可迭代对象
  1. 定义[Symbol.iterator]方法对象需实现[Symbol.iterator]方法,该方法返回一个包含next()的迭代器对象。next()每次调用返回{ value: 当前值, done: 布尔值 }。

    示例:计数器

    function createCounter(start, end) { let current = start; return { [Symbol.iterator]() { return { next() { if (current <= end) { return { value: current++, done: false }; } else { return { value: undefined, done: true }; } } }; } };}const myCounter = createCounter(1, 3);for (const num of myCounter) console.log(num); // 输出 1, 2, 3
  2. 关键点

    [Symbol.iterator]是对象可迭代的核心标识。

    迭代器通过next()管理状态,done: true终止迭代。

    展开运算符(如[...createCounter(5, 7)])同样依赖此协议。

二、生成器函数简化实现

生成器函数(function*)自动管理迭代状态,通过yield产出值,避免手动实现next()。

  1. 生成器函数作为[Symbol.iterator]

    function createCounterWithGenerator(start, end) { return { [Symbol.iterator]: function* () { for (let i = start; i <= end; i++) yield i; } };}const myGenCounter = createCounterWithGenerator(10, 12);for (const num of myGenCounter) console.log(num); // 输出 10, 11, 12
  2. 直接使用生成器函数生成器函数本身返回迭代器,可直接遍历:

    function* simpleGenerator() { yield 'Hello'; yield 'World'; yield '!';}for (const item of simpleGenerator()) console.log(item); // 输出 Hello, World, !
  3. 优势

    代码简洁:无需手动维护value和done。

    状态自动管理:yield暂停执行,下次调用从暂停处继续。

    适用复杂逻辑:如异步迭代、无限序列等。

三、for...of与迭代协议的协同
  1. 工作原理

    调用对象的[Symbol.iterator]获取迭代器。

    反复调用next(),检查done属性:

    done: false:将value赋给变量,执行循环体。

    done: true:终止循环。

  2. 与for...in的区别

    for...in遍历对象属性名(包括原型链),而for...of遍历可迭代对象的值。

    for...of仅适用于数组、字符串、Map、Set等实现迭代协议的对象。

四、应用场景
  1. 自定义数据结构如链表、树等,通过实现迭代协议统一遍历方式。
  2. 异步迭代结合async function*和for await...of处理异步数据流(如文件读取、网络请求)。
  3. 无限序列生成器可轻松实现无限序列(如斐波那契数列):function* fibonacci() { let [a, b] = [0, 1]; while (true) { yield a; [a, b] = [b, a + b]; }}
总结
  • 手动实现:通过[Symbol.iterator]和next()定义迭代逻辑,适合简单场景。
  • 生成器函数:使用function*和yield简化代码,适合复杂或状态管理需求。
  • 统一遍历:迭代协议使for...of和展开运算符能处理多种数据结构,提升代码灵活性。