在JavaScript中,为对象设置Symbol.iterator属性可使其支持for...of等迭代语法;该属性必须是无参函数,返回含next()方法的迭代器对象。

在 JavaScript 中,通过为对象设置 Symbol.iterator 属性,可以让它支持 for...of、扩展运算符([...obj])、解构赋值等原生迭代语法。关键在于:该属性必须是一个**无参函数**,且返回一个符合迭代器协议的对象(即有 next() 方法)。
让对象可被 for...of 遍历
最常见用途是使自定义对象能用 for...of 遍历。只需在对象上定义 [Symbol.iterator]() 方法,返回一个每次调用 next() 都产出新值的迭代器对象。
例如,实现一个从 0 开始、最多生成 3 个数字的可迭代对象:
const counter = {
[Symbol.iterator]() {
let step = 0;
return {
next() {
if (step < 3) {
return { value: step++, done: false };
} else {
return { value: undefined, done: true };
}
}
};
}
};
<p>for (const num of counter) {
console.log(num); // 输出 0, 1, 2
}复用已有的可迭代结构
如果内部已有数组、Set 或其他可迭代数据,可以直接委托给它们的迭代器,避免重复写逻辑。
立即学习“Java免费学习笔记(深入)”;
- 用
return this.values[Symbol.iterator]();直接返回数组的迭代器 - 或用
return [...this.values][Symbol.iterator]();转成新数组再迭代(适合需修改顺序或过滤时)
例如封装一个只读列表类:
class ReadOnlyList {
constructor(items) {
this.items = [...items]; // 拷贝一份
}
[Symbol.iterator]() {
return this.items[Symbol.iterator]();
}
}
<p>const list = new ReadOnlyList(['a', 'b', 'c']);
console.log([...list]); // ['a', 'b', 'c']支持多次遍历与状态隔离
每次调用 [Symbol.iterator]() 都应返回**全新迭代器实例**,确保多次遍历互不干扰。不能缓存并复用同一个迭代器对象。
- ✅ 正确:每次调用都新建闭包或新对象(如上面
counter示例) - ❌ 错误:把迭代器对象存在 this 上,然后反复返回它 —— 第二次
for...of会从上次中断处继续,甚至直接结束
反例(有问题):
class BadCounter {
constructor() {
this.iter = this.createIterator();
}
createIterator() { /* ... */ }
[Symbol.iterator]() {
return this.iter; // ❌ 同一个迭代器被多次返回
}
}配合生成器函数更简洁
用 function*(生成器函数)定义 [Symbol.iterator] 是最简洁、最推荐的方式。它天然满足迭代器协议,且自动管理状态和 done 标志。
重写前面的计数器:
const counter = {
[Symbol.iterator]: function* () {
for (let i = 0; i < 3; i++) {
yield i;
}
}
};生成器函数内部的 yield 会自动转换为 {value: ..., done: false};函数自然结束时自动返回 {done: true},无需手动判断。


















