要让对象支持for...of遍历,需定义[symbol.iterator]方法并返回符合迭代器协议的对象:该方法必须返回含next()的对象,next()每次调用返回{value, done},done为true表示结束。
要让一个对象支持 for...of 遍历,关键是在对象上定义 [symbol.iterator] 方法,且该方法必须返回一个符合迭代器协议的对象(即有 next() 方法,返回 { value, done } 形式的对象)。
让普通对象可遍历
默认情况下,普通对象不可被 for...of 遍历。只需添加 [Symbol.iterator] 方法即可:
- 方法名必须是
Symbol.iterator(用方括号计算属性名) - 返回值必须是迭代器对象:拥有
next()方法,每次调用返回{ value: ..., done: true|false } -
done: true表示遍历结束;done: false表示还有值,value是当前项
例如,让一个包含数字的自定义容器支持遍历:
const myCollection = {
items: [10, 20, 30],
[Symbol.iterator]() {
let index = 0;
return {
next: () => {
if (index for (const item of myCollection) {
console.log(item); // 输出 10, 20, 30
}
复用已有的迭代器(如数组)
如果内部数据本身已是可迭代的(比如数组、Set、Map),可以直接委托给它的迭代器,更简洁安全:
- 调用
this.items[Symbol.iterator]()获取原生迭代器 - 直接返回它,无需手动管理状态
改写上面例子:
[Symbol.iterator]() {
return this.items[Symbol.iterator]();
}
这样既支持 for...of,也能用于展开运算符([...myCollection])、解构等场景。
支持多次遍历(避免单次耗尽)
注意:迭代器通常是一次性的。如果希望对象能被多次遍历(比如两次 for...of),[Symbol.iterator] 每次都应返回**新的迭代器实例**,而不是复用同一个:
- 错误写法:缓存并重复返回同一个迭代器对象 → 第二次遍历时立即结束
- 正确写法:每次调用
[Symbol.iterator]都新建一个迭代器(如重新调用arr[Symbol.iterator]())
所以推荐始终返回新迭代器,尤其对数组、字符串这类内置可迭代类型。
配合生成器函数简化实现
用 function* 写 [Symbol.iterator] 是最直观的方式,引擎自动处理迭代器协议:
- 函数体用
yield逐个产出值 - 返回的生成器对象天然满足迭代器协议
- 代码更清晰,状态管理由 JS 引擎托管
示例:
[Symbol.iterator]: function* () {
for (const item of this.items) {
yield item;
}
}
或更简短:
[Symbol.iterator]: function* () {
yield* this.items;
}
不复杂但容易忽略:只要返回合规的迭代器对象,任何结构都能参与现代遍历语法。核心是协议,不是语法糖。
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南











