Generator迭代器不可重复使用,因其内部是单向执行状态机,耗尽后始终返回{value: undefined, done: true};需通过每次新建实例、转为数组或封装工厂函数实现“重复使用”效果。

Generator 生成的迭代器对象**不能重复使用**,一旦遍历结束(done: true),后续调用 next() 始终返回 { value: undefined, done: true },也无法重置或回退。这是由 Generator 的设计机制决定的,不是 bug,而是规范行为。
为什么不能重复使用?
Generator 迭代器内部维护一个**单向执行状态机**:每次 next() 推进到下一个 yield 或 return,函数上下文(变量、指针位置)被保存;一旦执行到底部或遇到 return,状态标记为“已耗尽”,引擎禁止恢复。这保证了惰性求值和资源可控性,但也意味着:
- 迭代器是**一次性消耗品**,不是可循环的数组
- 没有
reset()、rewind()或seek()方法 - 即使只调用了一次
next()就停住,再次调用仍继续,不会从头开始
如何实现“重复使用”效果?
实际开发中需要多次遍历,有几种可靠方式,核心思路都是**每次需要时新建一个迭代器**:
-
每次访问都新建 Generator 实例:把
function*调用写在 getter 或方法里,不缓存迭代器。适合数据源稳定、生成开销小的场景 -
提前展开为数组:用
Array.from(gen())或[...gen()]把所有值转成数组再反复用。适合数据量不大、内存可接受的情况 -
封装为可重入的类或工厂函数:暴露一个返回新迭代器的函数,而不是暴露迭代器本身。例如:
getIterator() { return myGenerator(); }
常见误操作与后果
直接缓存迭代器并反复调用 next() 是典型错误:
立即学习“Java免费学习笔记(深入)”;
- 第一次遍历后,再调用
it.next()得到{ value: undefined, done: true },后续永远如此 - 试图用
it[Symbol.iterator]()获取新迭代器会失败——Generator 实例本身不实现[Symbol.iterator](它自己就是迭代器) - 误以为
for...of会自动重启:实际上for...of内部只调用一次[Symbol.iterator],拿到的仍是那个已耗尽的迭代器
什么时候该用缓存,什么时候不该?
关键看使用模式:
- 如果只读一次(如流式处理日志、事件流),用私有字段缓存单例迭代器更高效
- 如果要多次
for...of、解构、Array.from,就不要缓存迭代器,而应缓存 Generator 函数本身或原始数据源 - 异步 Generator(如
async function*)尤其要注意:每次调用返回新迭代器,但内部可能复用连接——这时需在 Generator 内部做连接管理,而非靠外部缓存迭代器


















