迭代器对象必须有 next() 方法,每次调用返回 { value, done };而 for...of 实际作用于可迭代对象,即拥有返回该迭代器的 [Symbol.iterator]() 方法的对象。

for...of 循环本身就能直接消费迭代器对象,无需额外转换或手动调用 next() —— 只要该对象实现了 迭代协议(即拥有 [Symbol.iterator]() 方法并返回一个符合迭代器协议的对象),就可以被 for...of 遍历。
迭代器对象必须满足什么条件?
一个“可被 for...of 消费”的迭代器对象,其实分两层:
-
可迭代对象(Iterable):拥有
[Symbol.iterator]方法,该方法返回一个迭代器对象(Iterator); -
迭代器对象(Iterator):是一个有
next()方法的对象,每次调用返回形如{ value, done }的结果。
注意:for...of 实际上作用在可迭代对象上,而不是直接作用在迭代器对象上。但你可以把“手动创建的迭代器”再包一层,让它变成可迭代的。
常见误区:直接对普通迭代器用 for...of 会报错
比如这样写是不行的:
立即学习“Java免费学习笔记(深入)”;
你接手一个需求时,是不是经常这样:"改一个小字段 → 结果把不相关的代码也改了"、"需求说得很模糊 → 做着做着发现跑偏了"、"数据库加个字段 → 上线才发现漏了数据兼容"、"做了个新功能 → 一个月后自己都忘了当时怎么设计的"、"写到一半被中断 → 再回来不知道从哪继续";这个 Skill 就是专门解决这些问题的。 它会自动探测你的项目环境(JDK、Spring Boot、ORM、数据库、前端框架),记在
const iter = [1, 2, 3][Symbol.iterator]();
for (const v of iter) { /* TypeError: iter is not iterable */ }因为 iter 是个迭代器对象(有 next),但它没有 [Symbol.iterator] 方法,所以不是可迭代对象。
✅ 正确做法:要么遍历原数组(可迭代),要么让迭代器自己也支持迭代协议:
// 方式1:直接遍历可迭代对象(推荐)
for (const v of [1, 2, 3]) { console.log(v); }
<p>// 方式2:让迭代器变“可迭代”——加一个 Symbol.iterator
const iter = [1, 2, 3][Symbol.iterator]();
iter[Symbol.iterator] = () => iter; // 自我引用
for (const v of iter) { console.log(v); } // ✅ 可以运行如何自定义一个可被 for...of 消费的对象?
只需实现 [Symbol.iterator](),返回一个带 next() 的对象即可:
const countdown = {
from: 3,
[Symbol.iterator]() {
let current = this.from;
return {
next() {
if (current < 1) {
return { value: undefined, done: true };
}
return { value: current--, done: false };
}
};
}
};
<p>for (const n of countdown) {
console.log(n); // 输出 3, 2, 1
}哪些内置类型天然支持 for...of?
以下都是可迭代对象,可直接用于 for...of:
- Array、TypedArray
- String(按 Unicode 字符)
- Map、Set
- arguments 对象、NodeList 等类数组(部分环境)
- Generator 函数返回的生成器对象(它既是可迭代的,也是迭代器)
而 Object 默认不支持,因为没实现 [Symbol.iterator] —— 想遍历键值需用 Object.keys(obj) 或 Object.entries(obj) 包装后再用。

















