生成器基础

生成器返回一个迭代器对象 或者说是一个带迭代器的集合 也就是可迭代的对象

1
2
3
4
5
6
function* generator() {
const a = yield 1; // 暂停,返回 {value: 1, done: false}
return a; // 结束,返回 {value: a, done: true}
}

const gen = generator(); // 返回生成器对象(可迭代对象)

1. next() 方法传参机制(重点补充)

核心规则next(value) 的参数会成为上一个 yield 表达式的返回值

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
function* demo() {
console.log("开始");
const step1 = yield "第一步"; // next() 停在这里
console.log("step1:", step1); // step1: 外部传入1

const step2 = yield "第二步"; // next("外部传入1") 停在这里
console.log("step2:", step2); // step2: 外部传入2

return "结束";
}

const gen = demo();

console.log(gen.next());
// 开始 → {value: "第一步", done: false}

console.log(gen.next("外部传入1"));
// step1: 外部传入1 → {value: "第二步", done: false}

console.log(gen.next("外部传入2"));
// step2: 外部传入2 → {value: "结束", done: true}

注意:第一次调用 next() 传参是无效的,因为没有”上一个 yield”

2. throw() 方法 - 外部向内部抛错误(重点补充)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
function* errorDemo() {
try {
console.log("A: 开始执行");
const result = yield "第一步"; // 外部 throw() 在这里抛错
console.log("B: 收到:", result); // 如果上面有错误,这行不执行
} catch (error) {
console.log("C: 捕获错误:", error.message);
yield "错误已处理";
}
console.log("D: 继续执行");
}

const gen = errorDemo();

console.log(gen.next());
// A: 开始执行 → {value: "第一步", done: false}

console.log(gen.throw(new Error("外部错误")));
// C: 捕获错误: 外部错误 → {value: "错误已处理", done: false}

console.log(gen.next());
// D: 继续执行 → {value: undefined, done: true}

异常处理规则

  • 内部有 try-catch:错误被捕获,生成器继续执行
  • 内部无 try-catch:错误冒泡到外部,生成器终止

3. return() 方法 - 提前终止(新增)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
function* generator() {
try {
yield "第一步";
yield "第二步"; // return() 在这里终止
yield "第三步"; // 不会执行
} finally {
console.log("执行finally块");
yield "清理资源"; // finally 块仍会执行
}
}

const gen = generator();
console.log(gen.next()); // {value: "第一步", done: false}
console.log(gen.return("提前结束")); // 执行finally块 → {value: "清理资源", done: false}
console.log(gen.next()); // {value: "提前结束", done: true}

4. yield* - 委托给另一个生成器(语法补充)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
function* innerGenerator() {
yield "内部1";
yield "内部2";
}

function* outerGenerator() {
yield "外部开始";
yield* innerGenerator(); // 自动迭代内部生成器的每个 yield
yield "外部结束";
}

// 等价于手动迭代:
function* outerGeneratorManual() {
yield "外部开始";
for (const value of innerGenerator()) {
yield value;
}
yield "外部结束";
}

const gen = outerGenerator();
console.log([...gen]);
// ["外部开始", "内部1", "内部2", "外部结束"]

5. 生成器作为可迭代对象

1
2
3
4
5
6
7
8
9
10
11
12
function* counter() {
yield 1;
yield 2;
yield 3;
}

// 可用于所有迭代场景
for (const num of counter()) {
console.log(num); // 1, 2, 3
}

const arr = [...counter()]; // [1, 2, 3]

方法总结表

方法 作用 参数影响 返回值
next(value) 恢复执行 成为上一个 yield 的返回值 {value, done}
throw(error) 抛出错误 暂停位置抛出错误 {value, done}
return(value) 提前终止 成为生成器最终返回值 {value, done}

执行流程记忆要点

  1. 首次 next():从函数开始执行到第一个 yield
  2. 后续 next(value):从上次 yield 处恢复,value 成为该 yield 的返回值
  3. throw(error):在最近暂停的 yield 处抛出错误
  4. yield*:自动展开另一个生成器的所有值