在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 for (const num of counter) {
console.log(num); // 输出 0, 1, 2
}复用已有的可迭代结构
如果内部已有数组、Set 或其他可迭代数据,可以直接委托给它们的迭代器,避免重复写逻辑。
- 用
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']</p>支持多次遍历与状态隔离
每次调用 [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 生成器函数内部的 yield 会自动转换为 {value: ..., done: false};函数自然结束时自动返回 {done: true},无需手动判断。
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南











