关键是在对象上部署symbol.iterator方法,该方法须返回含next()的迭代器对象,next()返回{value, done};普通对象默认不支持for...of,需手动实现此接口才能遍历。

让自定义对象支持 for...of 遍历,关键是在对象上部署 Iterator 接口,也就是实现一个返回迭代器对象的 [Symbol.iterator] 方法。
什么是 Iterator 接口
Iterator 接口本质上是一个方法,其键名为内置符号 Symbol.iterator。当对象拥有这个方法,且该方法返回一个符合迭代器协议的对象(即有 next() 方法,返回形如 { value, done } 的对象),它就能被 for...of、扩展运算符、解构等消费。
手动实现 [Symbol.iterator] 方法
最直接的方式是给对象或其原型添加 [Symbol.iterator] 方法,返回一个迭代器对象。常见写法有三种:
-
返回生成器函数:最简洁清晰,推荐使用
<code>const obj = {<br> a: 1,<br> b: 2,<br> c: 3<br>};<br><br>obj[Symbol.iterator] = function* () {<br> yield this.a;<br> yield this.b;<br> yield this.c;<br>};<br><br>for (const val of obj) console.log(val); // 1, 2, 3</code> -
返回普通对象(手动实现 next):更底层,适合理解原理
<code>obj[Symbol.iterator] = function () {<br> const keys = Object.keys(this);<br> let index = 0;<br> return {<br> next: () => {<br> if (index return { value: this[keys[index++]], done: false };<br> } else {<br> return { value: undefined, done: true };<br> }<br> }<br> };<br>};</code> -
在类中定义:适合封装复用
<code>class Range {<br> constructor(start, end) {<br> this.start = start;<br> this.end = end;<br> }<br><br> *[Symbol.iterator]() {<br> for (let i = this.start; i yield i;<br> }<br> }<br>}<br><br>for (const n of new Range(1, 4)) console.log(n); // 1, 2, 3</code>
注意事项和常见坑
-
[Symbol.iterator]必须是**函数**,不能是箭头函数(否则无法正确访问this) - 迭代器对象的
next()方法必须返回{ value, done }结构,done: true表示结束,之后再调用仍应返回{ value: undefined, done: true } - 如果想让对象同时支持
for...in(遍历属性名)和for...of(遍历值),两者互不影响:for...in看的是可枚举属性,for...of看的是[Symbol.iterator] - 数组、字符串、Map、Set 等原生类型已内置该接口;普通对象(plain object)默认不支持
for...of,需手动添加
验证是否生效的小技巧
除了 for...of,还可以用以下方式快速测试:
-
Array.from(obj)—— 能转成数组说明接口可用 -
[...obj]—— 扩展运算符能展开,也说明实现了迭代器 -
obj[Symbol.iterator] instanceof Function—— 检查方法是否存在且为函数
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南











