<p>yield* 是 Generator 函数中实现原生迭代委托的关键语法,它直接将产出权交给符合可迭代协议的对象,支持零开销嵌套展开、返回值捕获及异常透传,非手动循环的语法糖。</p>

yield* 是 Generator 函数中专用于迭代委托的关键语法,它不手动循环、不构造新数组、不转换类型,而是把当前生成器的“产出权”直接交给另一个可迭代对象,实现零中间开销的嵌套展开。
必须满足可迭代协议
被 yield* 委托的目标必须实现 [Symbol.iterator] 方法。常见合法目标包括:
- 数组(
[1, [2, 3]])、Set、Map - 字符串(但需注意:它会逐字符产出,通常要主动排除)
- 另一个 Generator 函数调用结果(如
numbersGenerator()) - 自定义对象,只要其
Symbol.iterator方法返回合法迭代器
普通对象(如 {a: 1})默认不可迭代,直接 yield* {a: 1} 会抛 TypeError。
递归展开嵌套结构的写法
对嵌套数组、树形结构等,需在 yield* 前做类型判断,避免无限委托或误拆:
- 用
Array.isArray(item)判断是否为数组,是则递归yield* flatten(item) - 用
typeof item === 'string'排除字符串,防止被拆成字符 - 对
null或undefined提前跳过,否则 yield* 会报错
示例:
function* flatten(arr) {for (const item of arr) {
if (Array.isArray(item)) {
yield* flatten(item);
} else if (item != null && typeof item !== 'string') {
yield item;
}
}
}
yield* 的返回值能被捕获
当被委托的迭代器执行完毕并调用 return(value) 时,该 value 就成为 yield* 表达式的返回值,可用于收尾逻辑:
- 在子生成器末尾写
return "done" - 主生成器中用
const res = yield* subGen()拿到这个返回值 - 后续可基于
res继续 yield 或处理状态
和普通 yield + 循环的本质区别
手动遍历再 yield 是模拟委托,而 yield* 是原生委托:
- 手动方式:需要写 for-of、判断、yield,还无法自动传递 return 值和异常
- yield* 方式:一次指令启动整个子迭代流程,透传每个 yield、接收 return、转发 throw,语义清晰且性能更好
- 它不是语法糖,而是语言级的迭代流水线接驳机制

















