MST
星途 面试题库

面试题:JavaScript生成器中yield关键字的作用及使用场景

请详细阐述JavaScript生成器中yield关键字的作用,并举例说明至少两个其适用的使用场景。
28.3万 热度难度
编程语言JavaScript

知识考点

AI 面试

面试题答案

一键面试

yield关键字的作用

  1. 暂停和恢复函数执行:在生成器函数中,yield关键字用于暂停函数的执行,并返回紧跟其后的表达式的值。生成器函数是一种特殊的函数,调用它并不会立即执行函数体,而是返回一个迭代器对象。每次调用迭代器的next()方法时,生成器函数会从上次暂停的yield处继续执行,直到遇到下一个yield或者函数结束。
  2. 传递值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可以与Generatorco库(或者现代的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,使异步操作看起来更像同步代码。