面试题答案
一键面试yield关键字的作用
- 暂停和恢复函数执行:在生成器函数中,
yield
关键字用于暂停函数的执行,并返回紧跟其后的表达式的值。生成器函数是一种特殊的函数,调用它并不会立即执行函数体,而是返回一个迭代器对象。每次调用迭代器的next()
方法时,生成器函数会从上次暂停的yield
处继续执行,直到遇到下一个yield
或者函数结束。 - 传递值:
yield
不仅可以返回值给外部调用者,还可以通过next()
方法传递值到生成器内部。当生成器函数通过yield
暂停时,next()
方法传入的值会作为该yield
表达式的返回值。
适用场景举例
场景一:惰性求值(Lazy Evaluation)
在处理大量数据集合时,惰性求值可以避免一次性生成和处理所有数据,从而节省内存。例如,生成一个无限序列:
function* infiniteSequence() {
let i = 0;
while (true) {
yield i++;
}
}
const sequence = infiniteSequence();
console.log(sequence.next().value); // 输出: 0
console.log(sequence.next().value); // 输出: 1
console.log(sequence.next().value); // 输出: 2
在这个例子中,infiniteSequence
生成器函数不会一次性生成所有的数字,而是在每次调用next()
时生成下一个数字,这对于处理理论上无限的数据集合非常有用。
场景二:异步操作控制
yield
可以与Generator
和co
库(或者现代的async/await
语法糖的底层原理相关)结合,用于控制异步操作流程。例如,模拟异步读取文件操作:
const fs = require('fs');
const co = require('co');
function readFileAsync(filePath) {
return new Promise((resolve, reject) => {
fs.readFile(filePath, 'utf8', (err, data) => {
if (err) reject(err);
else resolve(data);
});
});
}
function* readFiles() {
const file1 = yield readFileAsync('file1.txt');
const file2 = yield readFileAsync('file2.txt');
console.log(file1 + file2);
}
co(readFiles()).catch(console.error);
在这个例子中,yield
暂停生成器函数的执行,等待readFileAsync
这个异步操作(返回Promise)完成。当Promise resolve时,yield
表达式返回Promise的resolved值,生成器函数继续执行。co
库负责自动处理生成器函数中的yield
,使异步操作看起来更像同步代码。