要让自定义对象支持for...of,需在原型上定义[symbol.iterator]方法,返回符合迭代器协议的对象:含next()方法,每次返回{value, done}。生成器函数是最简洁实现方式;手动实现则适用于分页、懒加载等精细控制场景。

要让自定义对象支持 for...of,关键是在其原型(或实例)上定义 [Symbol.iterator] 方法,返回一个符合迭代器协议的对象:即具有 next() 方法,每次调用返回 { value, done } 形式的对象。
理解迭代器协议的核心要求
标准迭代契约不关心数据怎么存、怎么取,只约定接口行为:
-
[Symbol.iterator]必须是无参函数,返回一个对象 - 该返回对象必须有
next()方法 -
next()每次调用返回{ value: any, done: boolean } - 当
done为true时,value可选(常用于终止信号)
为类添加 Symbol.iterator 的典型写法
推荐在类的原型上定义,复用性高。例如实现一个管理用户列表的业务类:
class UserCollection {
constructor(users = []) {
this.users = users;
}
*[Symbol.iterator]() {
for (const user of this.users) {
yield user;
}
}
}
// 使用
const coll = new UserCollection([
{ id: 1, name: '张三' },
{ id: 2, name: '李四' }
]);
for (const user of coll) {
console.log(user.name); // 张三、李四
}
这里用了生成器函数(function*),它天然满足迭代器协议——生成器函数执行后返回一个迭代器对象,自带合规的 next()。这是最简洁可靠的实现方式。
手动实现 next 而不依赖生成器
若需精细控制状态(如分页拉取、懒加载、带副作用的遍历),可手动构造迭代器对象:
class LazyOrderIterator {
constructor(orderIds) {
this.orderIds = orderIds;
this.index = 0;
}
[Symbol.iterator]() {
return this;
}
next() {
if (this.index
<p>要点:<code>[Symbol.iterator]()</code> 返回 <code>this</code> 是常见模式,但仅当该实例本身已具备 <code>next()</code> 且可被多次遍历(或设计为单次使用)时才适用;否则应返回新创建的独立迭代器实例,避免状态污染。</p>
<h3>注意边界与兼容性细节</h3>
<p>几个容易出错的地方:</p>
- 不要在实例上直接赋值
this[Symbol.iterator] = ...,否则每个实例都重复创建函数,浪费内存;优先挂载到prototype - 若对象是普通字面量(非类实例),可用
Object.defineProperty或计算属性语法添加:{ [Symbol.iterator]() { return {...} } } - 确保
next()总是返回对象,不能返回undefined或原始值,否则for...of会报错 - TypeScript 中需声明
[Symbol.iterator]: Iterator<t></t>类型,否则类型检查可能失败










