ES6 中的 Generator函数是一种特殊类型的函数,它允许你控制函数的执行流程,使其在执行过程中可以多次暂停和恢复。Generator 函数在定义时使用星号 * 作为后缀。
主要特性:
- 惰性计算:Generator 函数执行到 yield 表达式时会暂停,下一次再从上次暂停的地方继续执行。
- 多次迭代:与传统函数不同,Generator 函数可以被迭代多次,每次迭代都会返回一个新的值。
- 状态保持:Generator 函数在暂停和恢复时能够保持其内部状态。
可接受输入:在下一次迭代时,可以通过 next() 方法向 Generator 函数传递参数。
常用方法:
- next(value):继续执行 Generator 函数,并返回一个包含 value 和 done 属性的对象。value 是 yield 表达式返回的值,done 表示函数是否执行完毕。
- return(value):结束 Generator 函数的执行,返回一个包含 value 和 done 属性为 true 的对象。
- throw(error):向 Generator 函数中抛出错误。
1. 基本的 Generator 函数
function* helloWorld() {
console.log("Hello");
yield;
console.log("World");
}
let generator = helloWorld();
generator.next(); // 输出: Hello,但不会继续执行到 "World"
generator.next(); // 输出: World,并结束函数
2. 使用 yield 返回值
function* generateSequence() {
yield 1;
yield 2;
yield 3;
}
let sequenceGenerator = generateSequence();
console.log(sequenceGenerator.next()); // { value: 1, done: false }
console.log(sequenceGenerator.next()); // { value: 2, done: false }
console.log(sequenceGenerator.next()); // { value: 3, done: false }
console.log(sequenceGenerator.next()); // { value: undefined, done: true }
3. 在 for…of 循环中使用 Generator 函数
function* generateArrayOfNumbers() {
yield* [1, 2, 3];
}
for (let num of generateArrayOfNumbers()) {
console.log(num); // 依次输出 1, 2, 3
}
4. 向 Generator 函数传递参数
function* count() {
let count = 0;
while (true) {
count++; // 每次迭代计数加一
console.log(`Count: ${count}`);
yield count; // 返回当前计数
}
}
let counter = count();
counter.next(); // 开始计数
counter.next(); // 继续计数
// 传递参数给 Generator 函数(在这个例子中没有使用,但展示了如何传递)
counter.next(10); // 参数通常用于控制 Generator 函数的行为
5. 使用 try…catch 捕获 Generator 函数中的错误
function* generatorWithThrow() {
yield 1;
throw new Error("Something went wrong!");
yield 2;
}
let errorGen = generatorWithThrow();
try {
console.log(errorGen.next()); // { value: 1, done: false }
console.log(errorGen.next()); // 将抛出错误
} catch (e) {
console.error(e.message); // 输出:Something went wrong!
}
6. 使用 yield 委托给另一个 Generator 函数或可迭代对象*
function* delegateGenerator() {
yield* ["Hello", "World"];
}
function* rootGenerator() {
yield "Start";
yield* delegateGenerator();
yield "End";
}
let root = rootGenerator();
console.log(root.next()); // { value: "Start", done: false }
console.log(root.next()); // { value: "Hello", done: false }
console.log(root.next()); // { value: "World", done: false }
console.log(root.next()); // { value: "End", done: false }
console.log(root.next()); // { value: undefined, done: true }