在 JavaScript 中,对象需实现 Symbol.iterator 方法并返回符合迭代器协议的对象(含 next() 方法,返回 {value, done} 形式对象)才能支持 for...of 等语法;如 Range 类通过闭包维护 current 状态实现迭代。

在 JavaScript 中,通过实现 Symbol.iterator 方法,可以让任意对象支持 for...of、扩展运算符([...obj])、解构赋值等原生迭代语法。这不是“加个属性”那么简单,关键在于返回一个符合迭代器协议的对象。
什么是迭代器协议?
一个对象要能被迭代,它的 [Symbol.iterator] 方法必须返回一个**迭代器对象**,而该迭代器对象需满足:
- 有
next()方法; -
next()每次调用返回形如{ value: ..., done: true|false }的对象; - 当
done为true时,表示迭代结束,value可选(通常忽略)。
手动实现一个可迭代的范围类
比如想让 Range(1, 5) 支持 for...of 遍历 1 到 4:
class Range {
constructor(start, end) {
this.start = start;
this.end = end;
}
[Symbol.iterator]() {
let current = this.start;
return {
next: () => {
if (current < this.end) {
return { value: current++, done: false };
} else {
return { done: true };
}
}
};
}
}
// 使用
for (const n of new Range(1, 4)) {
console.log(n); // 1, 2, 3
}
利用生成器函数简化写法
手写 next() 容易出错,更推荐用 function* 生成器——它自动满足迭代器协议:
立即学习“Java免费学习笔记(深入)”;
class Range {
constructor(start, end) {
this.start = start;
this.end = end;
}
*[Symbol.iterator]() {
for (let i = this.start; i < this.end; i++) {
yield i;
}
}
}
生成器函数内部用 yield 控制产出,JS 引擎自动封装成合规迭代器,逻辑清晰且不易出错。
注意:不可多次复用的迭代器
每次调用 [Symbol.iterator]() 都应返回**新的迭代器实例**。否则像 [...range, ...range] 这类操作会因共享状态而异常:
- 错误示例:把迭代器缓存在实例属性里,重复返回同一对象;
- 正确做法:每次调用都新建迭代状态(如上面的
current局部变量,或生成器函数每次执行都创建新上下文)。


















