合法迭代器对象必须有next()方法,且每次调用返回{value: any, done: boolean}结构的对象;done为true表示遍历结束,value可存在(如return值)。

JavaScript 迭代器不是语法糖,而是一个有明确接口约定的对象;它让任意对象支持 for-of 循环的关键,在于实现 [Symbol.iterator]() 方法并返回一个符合迭代器协议的对象。
迭代器对象必须满足什么结构?
一个合法的迭代器对象,必须有 next() 方法,且每次调用返回形如 { value: any, done: boolean } 的对象。其中:done 为 true 表示遍历结束,value 是当前项(即使 done: true,value 仍可存在,比如 return 值)。
常见错误现象:
- 手动写的
next()没返回对象 →TypeError: Iterator result undefined is not an object -
done忘记设为布尔值(比如写成字符串"true")→for-of不停止 - 多次调用
next()后状态没推进(比如总返回第一个元素)→ 死循环
for-of 背后到底在调什么?
for-of 不是直接操作数组或字符串,而是先尝试调用目标对象的 [Symbol.iterator] 方法。如果没找到,就报错 TypeError: ... is not iterable;如果找到了,就反复调它的返回值的 next(),直到 done: true。
立即学习“Java免费学习笔记(深入)”;
实操要点:
- 原生可迭代对象(
Array、String、Map、Set、TypedArray)都自带[Symbol.iterator] - 普通对象默认不可迭代,加了
[Symbol.iterator](){ return {...} }才能进for-of -
for-of无法遍历类数组对象(如arguments、NodeList)除非它们显式实现了迭代器协议
手写一个可被 for-of 消费的范围迭代器
下面这个 range 函数返回的对象,既能用 for-of 遍历,也能手动调 next():
function range(start, end) {
return {
[Symbol.iterator]() {
let current = start;
return {
next() {
if (current < end) {
return { value: current++, done: false };
}
return { done: true };
}
};
}
};
}
for (const n of range(2, 5)) {
console.log(n); // 2, 3, 4
}
注意点:
-
[Symbol.iterator]必须是函数,且每次调用都应返回**新**的迭代器对象(否则多个for-of共享状态会出错) - 上面例子中,
next()内部用闭包保存current,保证每次迭代独立 - 如果想支持无限迭代(如
range(0)),需自行控制终止逻辑,for-of本身不提供中断机制
真正容易被忽略的是:迭代器协议是“单向消耗”的——一旦 next() 返回 { done: true },后续再调就该持续返回相同结果,不能重置。很多自定义迭代器忘了这点,导致重复遍历时行为异常。











