return() 和 throw() 是迭代器可选的清理方法:return() 在 for...of 提前退出时执行同步或异步资源清理;throw() 主要用于 Generator 响应外部异常并做内部状态重置,二者均不保证被调用。

在 JavaScript 迭代器中,return() 和 throw() 都是可选方法,核心作用不是控制流程,而是做**清理收尾工作**。它们是否被调用、何时被调用,取决于外部使用方式,而非迭代器自身逻辑。
return() 是提前退出时的资源清理钩子
当 for...of 循环因 break、continue、return 或异常而中断,引擎会尝试调用迭代器的 return() 方法——前提是该方法存在且为函数。
- 它必须返回一个对象(规范要求),通常形如
{ done: true } - 适合关闭文件句柄、取消定时器、终止 WebSocket 连接、释放内存引用等同步清理
- 注意:浏览器和运行时并不保证它一定被调用(比如迭代器被丢弃未进入循环,或直接多次调用
next()) - 示例场景:
for (const item of myIterator) {
console.log(item);
break; // 此时触发 return()
}
throw() 是异常穿透时的协同清理入口
throw() 主要配合 Generator 函数设计,在外部向迭代器内部“注入”异常(比如 for...of 中抛出错误后,引擎可能调用它)。普通手写迭代器极少需要实现它。
- 它的典型用途是让生成器能响应外部中断,执行内部状态重置或清理
- 如果迭代器内部有挂起的异步操作(如 Promise),
throw()可用于拒绝待处理的 Promise,避免悬垂 - 不建议在
throw()中抛出新异常(除非有意传播),否则可能掩盖原始错误 - 与
return()类似,它也需返回符合迭代器协议的对象
异步迭代器中的 return() 更关键也更复杂
对于 AsyncIterator(即支持 for await...of 的对象),return() 返回的是 Promise,这使它天然适配异步清理任务。
- 例如:等待 HTTP 请求取消、等待数据库连接优雅关闭、等待 WebSocket 发送完最后一条消息再断开
- 引擎会在
for await...of提前退出时,自动await这个return()返回的 Promise 完成后再继续 - 务必避免在
return()的 Promise 中产生未捕获的 rejection,否则会触发 unhandledrejection 事件 - 不能依赖它一定执行——仍需在应用层主动管理生命周期(如显式调用清理函数)
如何判断它们是否生效
最可靠的方式是**在方法体内加日志或调试断点**,然后构造明确触发条件:
- 用
for...of+break测试return() - 用
for...of+throw new Error()测试return()和throw()的调用顺序(return()先于异常抛出) - 对异步迭代器,用
for await...of+break,观察return()返回的 Promise 是否被 await - 检查控制台是否有
UnhandledPromiseRejectionWarning,可反推return()内部 Promise 是否出错

















