<p>yield* 实现深层嵌套 Generator 树控制流的关键是精准委托:仅对满足可迭代协议、类型安全、边界清晰的节点使用,需前置判断数组、对象、自定义类等合法性,显式排除字符串,利用 return 值收束子树状态,主动防御异常与循环引用。</p>

巧用 yield* 实现深层嵌套 Generator 树的控制流平滑委托,关键不在“展开得多”,而在“交得准、接得稳、退得清”。它不是自动递归器,而是可控的控制权接驳点——只有明确满足可迭代协议、类型安全、边界清晰的子结构,才该被 yield* 接管。
只对真正可迭代且语义明确的节点使用 yield*
深层树中混杂数组、对象、字符串、null、自定义类等,yield* 会直接报错或误展开(如把字符串拆成字符)。必须前置判断:
- 用
Array.isArray(item)确认是数组再yield* flatten(item) - 用
item != null && typeof item === 'object'过滤掉原始值和 null/undefined - 对自定义节点,确保其有
[Symbol.iterator]方法并返回合法迭代器,否则改用普通yield输出整个节点 - 显式排除字符串:
typeof item !== 'string',避免意外逐字符产出
用 return 值收束子树状态,实现分层响应
yield* 不仅转发 yield,还捕获子生成器的 return 值。这在树形遍历中可用于标记子分支完成、汇总统计或触发清理:
- 在递归子生成器末尾写
return {count: n, depth: d} - 父层用
const result = yield* traverseNode(node)拿到该返回值 - 后续可基于
result.count决定是否继续 yield 其他内容,或记录日志
异常与中断需主动防御,不能依赖透传兜底
yield* 会透传 throw() 和 return(),但前提是子迭代器没提前崩溃。深层树中某节点抛出未捕获错误,会导致整条委托链中断:
- 对不可信输入(如外部 API 返回的嵌套结构),在外层
try...catch包裹yield*调用 - 若某子生成器可能异步失败或需降级处理,不要裸写
yield* riskyGen(),而应封装一层带 fallback 的代理生成器 - 关闭资源(如打开的迭代器句柄)应在子生成器内部
finally块中完成,yield*不自动管理生命周期
避免无意中创建隐式委托环
树结构若含循环引用(如 parent 指针回指),yield* 会无限递归直至栈溢出。这不是语法缺陷,而是设计约束:
- 遍历时维护已访问节点 Set,遇到重复引用直接跳过或报错提示
- 对含反向引用的结构,不将 parent 字段纳入迭代路径,改用显式字段白名单(如只遍历
children) - 调试时可在递归入口加深度计数器,超阈值强制终止并抛出
RangeError

















