for...of 的本质是向对象索取迭代器并持续调用 next() 获取 {value, done},依赖可迭代协议(提供 Symbol.iterator 方法)和迭代器协议(next 返回规范对象);原生数组、字符串等支持,普通对象需手动实现。

for...of 的本质不是“遍历数组”或“遍历字符串”,而是“向对象要一个迭代器,然后持续取值直到结束”。它不依赖数据结构类型,只认两个硬性约定:可迭代协议 + 迭代器协议。
可迭代协议:对象必须提供 Symbol.iterator 方法
一个对象要想被 for...of 遍历,首先要能“产出迭代器”。这靠实现 Symbol.iterator 方法来达成——它必须是无参函数,返回一个符合迭代器协议的对象。
- 原生支持该协议的有:Array、String、Map、Set、TypedArray、arguments、NodeList 等
- 普通对象(如
{a: 1, b: 2})默认没有[Symbol.iterator],直接用于 for...of 会报错 - 你可以手动挂载:
obj[Symbol.iterator] = function() { return {...} }
迭代器协议:next() 方法返回 { value, done }
Symbol.iterator 返回的那个对象,就是迭代器。它的核心只有一个方法:next()。每次调用,都必须返回形如 { value: ..., done: true|false } 的对象。
- value 是当前产出的值(可以是任意类型,包括 undefined)
-
done 是布尔值:false 表示还有值可取;true 表示遍历结束,后续调用也应返回
{ value: undefined, done: true } - for...of 内部就是反复调用 next(),读 value、检查 done,done 为 true 就停
for...of 的实际执行步骤(伪逻辑)
当你写 for (const x of obj) { ... },引擎在背后做了三件事:
- 调用
obj[Symbol.iterator](),拿到迭代器对象 - 循环执行
iterator.next() - 每次拿到结果后,若
done === false,就把value赋给x并执行循环体;若done === true,立即退出循环
自己造一个能 for...of 的对象很简单
比如想遍历从 10 到 12 的整数:
const range = {
from: 10,
to: 12,
[Symbol.iterator]() {
let current = this.from;
return {
next() {
if (current <= this.to) {
return { value: current++, done: false };
}
return { value: undefined, done: true };
}
};
}
};
for (const n of range) console.log(n); // 10, 11, 12

















