javascript中自定义对象支持for...of等遍历语法需实现迭代器协议:对象必须有[symbol.iterator]方法,返回符合{value, done}结构的迭代器;推荐用生成器函数function*实现,语义清晰且天然合规。

JavaScript 中通过实现迭代器协议(Iterator Protocol),可以让自定义对象支持 for...of、扩展运算符([...obj])、解构赋值等原生遍历语法。核心是让对象拥有一个返回迭代器的 [Symbol.iterator] 方法,而该迭代器需符合“迭代器协议”:每次调用 next() 返回形如 { value, done } 的对象。
让对象可被 for...of 遍历
只需在对象上定义 [Symbol.iterator] 方法,返回一个满足迭代器协议的对象即可。常见写法是返回一个闭包函数或生成器函数。
- 手动实现:返回一个对象,其
next()方法控制每次返回的值和结束状态 - 推荐用生成器函数:
function* () { yield ... },天然符合协议,语义清晰、逻辑易维护
例如,实现一个倒序遍历数组的自定义迭代器:
const reverseArray = arr => {
return {
[Symbol.iterator]: function* () {
for (let i = arr.length - 1; i >= 0; i--) {
yield arr[i];
}
}
};
};
<p>for (const item of reverseArray([1, 2, 3])) {
console.log(item); // 3 → 2 → 1
}</p>迭代器协议的关键细节
一个合法的迭代器必须满足:每次调用 next() 返回一个对象,包含 value(当前产出值)和 done(布尔值,表示是否遍历完毕)。一旦 done: true,后续调用 next() 仍应返回 { value: undefined, done: true }。
-
value可以是任意类型,包括undefined;但若done为true,value通常被忽略(除非有特殊语义) - 迭代器可以是“耗尽型”的:多次调用
for...of不会重置状态,除非每次新建迭代器(如生成器函数每次调用都返回新迭代器) - 可选实现
return()和throw()方法,用于提前终止或错误注入(如break或for...of中抛错时触发)
配合生成器函数简化开发
生成器函数(function*)是实现迭代器最自然的方式。它自动返回一个符合协议的迭代器,并支持 yield 暂停/恢复执行,适合处理异步、惰性计算、树结构遍历等场景。
- 每个
yield对应一次next()调用的value - 函数结束或执行
return时,done变为true,value为返回值 - 可搭配
yield*委托其他可迭代对象,复用已有逻辑
例如,实现斐波那契数列的无限迭代器:
function* fibonacci() {
let a = 0, b = 1;
while (true) {
yield a;
[a, b] = [b, a + b];
}
}
<p>const fib = fibonacci();
console.log(fib.next().value); // 0
console.log(fib.next().value); // 1
console.log(fib.next().value); // 1
console.log([...fib].slice(0, 10)); // [0,1,1,2,3,5,8,13,21,34](注意:实际运行需限制长度)</p>实际应用中的注意事项
自定义迭代器不是“语法糖”,而是真正改变数据消费方式的底层机制。使用时需注意:
- 确保
[Symbol.iterator]是一个无参函数,且每次调用都返回**新迭代器**(否则多次for...of会互相干扰) - 避免在迭代器中做昂贵同步操作;如需异步,可用
async function*创建异步迭代器(配合for await...of) - 调试时可通过手动调用
next()观察状态,或用Array.from(iterable)快速转为数组验证行为 - 类中定义时,推荐用 getter 或方法形式挂载
[Symbol.iterator],保持实例隔离性
不复杂但容易忽略。
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南











