9.3 生成器函数(function*)与 yield
9.3 生成器函数(function*)与 yield
生成器函数(Generator Function)是 ES6 引入的一种特殊函数,用于生成一个迭代器。通过 function* 和 yield 关键字,可以更简洁地实现自定义迭代器。本节将详细介绍生成器函数的用法及其应用场景。
9.3.1 生成器函数的基本概念
生成器函数使用 function* 定义,内部通过 yield 关键字产生值。调用生成器函数时,返回一个生成器对象,该对象符合迭代器协议。
1. 定义生成器函数
function* generatorFunction() {
yield "First";
yield "Second";
yield "Third";
}
2. 生成器对象
生成器函数返回的生成器对象是一个迭代器,可以通过 next() 方法获取值:
const generator = generatorFunction();
console.log(generator.next()); // 输出 { value: "First", done: false }
console.log(generator.next()); // 输出 { value: "Second", done: false }
console.log(generator.next()); // 输出 { value: "Third", done: false }
console.log(generator.next()); // 输出 { value: undefined, done: true }
9.3.2 yield 关键字
yield 关键字用于暂停生成器函数的执行,并返回一个值。每次调用 next() 方法时,生成器函数会从上次暂停的位置继续执行。
1. 基本用法
function* generatorFunction() {
yield 1;
yield 2;
yield 3;
}
const generator = generatorFunction();
for (const value of generator) {
console.log(value); // 输出 1, 2, 3
}
2. 传递值
next() 方法可以传递一个值,该值会作为 yield 表达式的返回值:
function* generatorFunction() {
const a = yield "First";
const b = yield "Second";
yield a + b;
}
const generator = generatorFunction();
console.log(generator.next()); // 输出 { value: "First", done: false }
console.log(generator.next(2)); // 输出 { value: "Second", done: false }
console.log(generator.next(3)); // 输出 { value: 5, done: false }
console.log(generator.next()); // 输出 { value: undefined, done: true }
9.3.3 生成器函数的应用场景
1. 自定义迭代器
生成器函数可以简化自定义迭代器的实现:
function* range(start, end) {
for (let i = start; i <= end; i++) {
yield i;
}
}
for (const value of range(1, 3)) {
console.log(value); // 输出 1, 2, 3
}
2. 惰性求值
生成器函数可以实现惰性求值,只在需要时计算值:
function* fibonacci() {
let prev = 0,
curr = 1;
while (true) {
yield curr;
[prev, curr] = [curr, prev + curr];
}
}
const fib = fibonacci();
console.log(fib.next().value); // 输出 1
console.log(fib.next().value); // 输出 1
console.log(fib.next().value); // 输出 2
console.log(fib.next().value); // 输出 3
3. 异步编程
生成器函数可以与 Promise 结合,实现更简洁的异步编程:
function* asyncGenerator() {
const result1 = yield fetch("https://api.example.com/data1");
const result2 = yield fetch("https://api.example.com/data2");
return [result1, result2];
}
function runAsyncGenerator(generator) {
const iterator = generator();
function handle(iteratorResult) {
if (iteratorResult.done) {
return iteratorResult.value;
}
const promise = iteratorResult.value;
return promise.then((res) => handle(iterator.next(res)));
}
return handle(iterator.next());
}
runAsyncGenerator(asyncGenerator).then((results) => {
console.log(results);
});
9.3.4 示例代码
示例 1:自定义迭代器
function* range(start, end) {
for (let i = start; i <= end; i++) {
yield i;
}
}
for (const value of range(1, 3)) {
console.log(value); // 输出 1, 2, 3
}
示例 2:惰性求值
function* fibonacci() {
let prev = 0,
curr = 1;
while (true) {
yield curr;
[prev, curr] = [curr, prev + curr];
}
}
const fib = fibonacci();
console.log(fib.next().value); // 输出 1
console.log(fib.next().value); // 输出 1
console.log(fib.next().value); // 输出 2
console.log(fib.next().value); // 输出 3
示例 3:异步编程
function* asyncGenerator() {
const result1 = yield fetch("https://api.example.com/data1");
const result2 = yield fetch("https://api.example.com/data2");
return [result1, result2];
}
function runAsyncGenerator(generator) {
const iterator = generator();
function handle(iteratorResult) {
if (iteratorResult.done) {
return iteratorResult.value;
}
const promise = iteratorResult.value;
return promise.then((res) => handle(iterator.next(res)));
}
return handle(iterator.next());
}
runAsyncGenerator(asyncGenerator).then((results) => {
console.log(results);
});
9.3.5 总结
- 生成器函数:使用
function*定义,通过yield产生值。 - 生成器对象:符合迭代器协议,可以通过
next()方法获取值。 - 应用场景:自定义迭代器、惰性求值、异步编程。
通过掌握生成器函数和 yield 关键字,你可以编写更简洁、更灵活的代码。在接下来的学习中,我们将继续探索 JavaScript 的其他高级特性。
思考题:
- 生成器函数与普通函数的主要区别是什么?
- 如何通过生成器函数实现惰性求值?
- 在什么情况下应该使用生成器函数处理异步操作?
#前端开发
分享于 2025-03-21