要让普通自定义对象支持 for...of 循环,关键在于实现 Symbol.iterator 方法,返回含 next() 的迭代器对象,next() 返回 {value, done} 形式结果。

要让普通自定义对象支持 for...of 循环,关键在于让它具备可迭代协议(iterable protocol),即实现 [Symbol.iterator] 方法,返回一个符合迭代器协议(iterator protocol)的对象。
自定义对象必须实现 [Symbol.iterator] 方法
JavaScript 的 for...of 会自动查找对象身上的 Symbol.iterator 方法。如果存在且返回一个对象,该对象必须有 next() 方法,每次调用返回形如 { value: ..., done: true|false } 的结果。
-
next()必须是函数,不能是箭头函数(否则无法正确绑定this) -
done: true表示遍历结束;done: false(或未提供)表示还有值 - 返回的
value就是for...of每次接收到的值
手动实现一个简单的迭代器
例如,给一个包含内部数组的类添加迭代能力:
class MyContainer {
constructor(items) {
this.items = items;
}
[Symbol.iterator]() {
let index = 0;
return {
next: () => {
if (index < this.items.length) {
return { value: this.items[index++], done: false };
} else {
return { value: undefined, done: true };
}
}
};
}
}
const container = new MyContainer(['a', 'b', 'c']);
for (const item of container) {
console.log(item); // 'a', 'b', 'c'
}
复用内置迭代器提升简洁性
如果内部数据本身可迭代(如数组、Set、Map),可以直接委托其迭代器,避免手动管理状态:
立即学习“Java免费学习笔记(深入)”;
- 返回
this.items[Symbol.iterator]()即可(注意加括号调用) - 这样既安全又高效,还能继承原数据的遍历行为(比如 Map 默认遍历键值对)
class MyList {
constructor(arr) {
this.data = arr;
}
[Symbol.iterator]() {
return this.data[Symbol.iterator]();
}
}
注意不要返回普通对象或错误结构
常见错误包括:
- 把
[Symbol.iterator]写成普通方法名(如iterator()),不带Symbol.前缀 -
next()返回没有value或done属性的对象 -
[Symbol.iterator]返回的是非对象(如null、undefined、字符串等) - 多次调用
for...of时,因共享状态导致后续遍历异常(建议每次返回新迭代器)
只要确保 [Symbol.iterator] 返回一个拥有合规 next() 方法的对象,你的自定义对象就能自然融入 JavaScript 的迭代生态。


















