JavaScript中yield生成器函数
在 JavaScript 中, 生成器函数 Generator Function 是一种特殊的函数,它允许你在函数执行过程中暂停和恢复。生成器函数通过 function* 语法定义,并使用 yield 关键字 来控制函数的执行流程。生成器函数返回一个生成器对象,该对象遵循迭代器协议,可以逐步生成值。
以下是生成器函数的详细解析:
1. 基本语法
生成器函数使用 function* 定义,函数体内可以使用 yield 关键字来暂停函数的执行并返回一个值。
1 function* myGenerator() { 2 yield 1; 3 yield 2; 4 yield 3; 5 }
function*:定义生成器函数的关键字。
yield:暂停函数执行并返回一个值。每次调用生成器对象的 next() 方法时,函数会从上次暂停的地方继续执行。
2. 生成器对象
生成器函数调用时不会立即执行函数体,而是返回一个生成器对象。这个生成器对象是一个迭代器,可以通过 next() 方法逐步执行生成器函数。
1 const gen = myGenerator(); 2 3 console.log(gen.next()); // { value: 1, done: false } 4 console.log(gen.next()); // { value: 2, done: false } 5 console.log(gen.next()); // { value: 3, done: false } 6 console.log(gen.next()); // { value: undefined, done: true }
next():恢复生成器函数的执行,直到遇到下一个 yield 或函数结束。
返回一个对象,包含两个属性:
value:yield 表达式的值。
done:布尔值,表示生成器函数是否已经执行完毕。
3. yield 关键字
yield 是生成器函数的核心关键字,它的作用如下:
1. 暂停函数执行:当生成器函数执行到 yield 时,会暂停执行并返回 yield 后面的值;
2. 恢复函数执行:当调用生成器对象的 next() 方法时,函数会从上次暂停的地方继续执行,直到遇到下一个 yield 或函数结束;
1 function* myGenerator() { 2 yield "Hello"; 3 yield "World"; 4 } 5 6 const gen = myGenerator(); 7 8 console.log(gen.next().value); // 'Hello' 9 console.log(gen.next().value); // 'World' 10 console.log(gen.next().done); // true 11
4. yield* 表达式
yield* 用于委托给另一个生成器或可迭代对象(如数组、字符串等)。它允许在一个生成器函数中调用另一个生成器函数。
1 function* generator1() { 2 yield 1; 3 yield 2; 4 } 5 6 function* generator2() { 7 yield* generator1(); // 委托给 generator1 8 yield 3; 9 } 10 11 const gen = generator2(); 12 13 console.log(gen.next().value); // 1 14 console.log(gen.next().value); // 2 15 console.log(gen.next().value); // 3 16 console.log(gen.next().done); // true
5. 生成器函数的特性
5.1. 惰性求值
生成器函数是惰性的,只有在调用 next() 时才会执行。这使得生成器非常适合处理大量数据或无限序列。
1 function* infiniteSequence() { 2 let i = 0; 3 while (true) { 4 yield i++; 5 } 6 } 7 8 const gen = infiniteSequence(); 9 10 console.log(gen.next().value); // 0 11 console.log(gen.next().value); // 1 12 console.log(gen.next().value); // 2 13 // 可以无限调用
5.2. 双向通信
生成器函数不仅可以通过 yield 返回值,还可以通过 next() 方法接收外部传入的值。
1 function* generator() { 2 const x = yield "Hello"; 3 yield x; 4 } 5 6 const gen = generator(); 7 8 console.log(gen.next().value); // 'Hello' 9 console.log(gen.next(42).value); // 42
第一次调用 next() 时,生成器函数执行到 yield 'Hello' 并暂停。
第二次调用 next(42) 时,42 会作为 yield 表达式的值传入,生成器函数继续执行。
5.3. 提前终止
生成器对象提供了 return() 和 throw() 方法,可以提前终止生成器函数的执行。
return(value):终止生成器函数并返回指定的值。
throw(error):在生成器函数内部抛出一个错误。
1 function* generator() { 2 yield 1; 3 yield 2; 4 yield 3; 5 } 6 7 const gen = generator(); 8 9 console.log(gen.next().value); // 1 10 console.log(gen.return(42).value); // 42 11 console.log(gen.next().done); // true
6. 生成器函数的应用场景
6.1. 惰性求值
生成器函数非常适合处理大量数据或无限序列,因为它只在需要时生成值。
1 function* fibonacci() { 2 let [prev, curr] = [0, 1]; 3 while (true) { 4 yield curr; 5 [prev, curr] = [curr, prev + curr]; 6 } 7 } 8 9 const fib = fibonacci(); 10 11 console.log(fib.next().value); // 1 12 console.log(fib.next().value); // 1 13 console.log(fib.next().value); // 2 14 console.log(fib.next().value); // 3 15 console.log(fib.next().value); // 5
6.2. 异步编程
在 async/await 出现之前,生成器函数常用于简化异步编程。通过结合 Promise 和生成器,可以实现类似于 async/await 的效果。
1 function* asyncGenerator() { 2 const result1 = yield new Promise((resolve) => 3 setTimeout(() => resolve(1), 1000) 4 ); 5 const result2 = yield new Promise((resolve) => 6 setTimeout(() => resolve(2), 1000) 7 ); 8 return result1 + result2; 9 } 10 11 function runGenerator(generator) { 12 const gen = generator(); 13 14 function handle(result) { 15 if (result.done) return Promise.resolve(result.value); 16 return Promise.resolve(result.value).then((res) => { 17 return handle(gen.next(res)); 18 }); 19 } 20 21 return handle(gen.next()); 22 } 23 24 runGenerator(asyncGenerator).then(console.log); // 3
6.3. 自定义迭代器
生成器函数可以用于创建自定义迭代器,简化迭代器的实现。
1 const myIterable = { 2 *[Symbol.iterator]() { 3 yield 1; 4 yield 2; 5 yield 3; 6 }, 7 }; 8 9 for (const value of myIterable) { 10 console.log(value); // 1, 2, 3 11 }
7. 总结
1. 生成器函数使用 function* 定义,通过 yield 暂停和恢复执行;
2. 生成器函数返回一个生成器对象,该对象是一个迭代器,可以通过 next() 方法逐步执行;
3. yield* 用于委托给另一个生成器或可迭代对象;
4. 生成器函数适用于惰性求值、异步编程和自定义迭代器等场景;
生成器函数提供了一种强大的控制流机制,使得你可以更灵活地管理函数的执行过程。
原文链接:https://blog.csdn.net/weixin_40629244/article/details/146167217