JavaScript 生成器

在JavaScript中,生成器提供了一种与函数迭代器协同工作的新方法。

使用生成器,

  • 您可以在函数内的任何位置暂停函数的执行
  • 并从暂停的位置继续执行代码

创建JavaScript生成器

要创建生成器,您首先需要使用function*符号定义一个生成器函数。生成器函数的对象称为生成器。

// define a generator function
function* generator_function() {
   ... .. ...
}

// creating a generator
const generator_obj = generator_function();

注意:生成器函数用*表示。您可以选择使用function* generatorFunc() {...}function *generatorFunc(){...}来创建它们。


使用yield暂停执行

如上所述,您可以在不执行整个函数体的情况下暂停生成器函数的执行。为此,我们使用yield关键字。例如,

// generator function
function* generatorFunc() {

    console.log("1. code before the first yield");
    yield 100;
    
   console.log("2. code before the second yield");
    yield 200;
}

// returns generator object
const generator = generatorFunc();

console.log(generator.next());

输出

1. code before the first yield
{value: 100, done: false}

这里,

  • 创建了一个名为generator的生成器对象。
  • 当调用generator.next()时,将执行到第一个yield的代码。遇到yield时,程序将返回值并暂停生成器函数。

注意:在使用生成器对象之前,您需要将其分配给一个变量。


多个yield语句的工作原理

yield表达式返回值。但是,与return语句不同,它不会终止程序。这就是为什么您可以从最后一个yield位置继续执行代码。例如,

function* generatorFunc() {

    console.log("1. code before first yield");
    yield 100;

   console.log("2. code before the second yield");
    yield 200;

    console.log("3. code after the second yield");
}

const generator = generatorFunc();

console.log(generator.next());
console.log(generator.next());
console.log(generator.next());

输出

1. code before first yield
{value: 100, done: false}
2. code before second yield
{value: 200, done: false}
3. code after the second yield
{value: undefined, done: true}

以下是此程序的运行方式。

  • 第一个generator.next()语句执行到第一个yield语句的代码,并暂停程序的执行。
  • 第二个generator.next()从暂停的位置开始执行程序。
  • 当访问完所有元素后,它将返回{value: undefined, done: true}
Working of generator function in JavaScript
JavaScript生成器函数的工作原理

向生成器函数传递参数

您还可以向生成器函数传递参数。例如,

// generator function
function* generatorFunc() {

    // returns 'hello' at first next()
    let x = yield 'hello';
    
    // returns passed argument on the second next()
    console.log(x);
    console.log('some code');

    // returns 5 on second next()
    yield 5;
    
}

const generator = generatorFunc();

console.log(generator.next());
console.log(generator.next(6));
console.log(generator.next());

输出

{value: "hello", done: false}
6
some code
{value: 5, done: false}
{value: undefined, done: true}

在上面的程序中,

  • 第一个generator.next()返回yield的值(在本例中为'hello')。但是,该值未分配给let x = yield 'hello';中的变量x
    {value: "hello", done: false}
  • 当遇到generator.next(6)时,代码将再次从let x = yield 'hello';开始执行,并且参数6将被分配给x。此外,其余代码将执行到第二个yield
    6
    some code
    {value: 5, done: false}
  • 当执行第三个next()时,程序将返回{value: undefined, done: true}。这是因为没有其他yield语句了。
    {value: undefined, done: true}

生成器用于实现可迭代对象

生成器提供了一种更简单的方式来实现迭代器

如果您想手动实现迭代器,则必须创建一个带有next()方法的迭代器并保存状态。例如,

// creating iterable object
const iterableObj = {

    // iterator method
    [Symbol.iterator]() {
        let step = 0;
        return {
            next() {
                step++;
                if (step === 1) {
                    return { value: '1', done: false};
                 }
                else if (step === 2) {
                    return { value: '2', done: false};
                }
                else if (step === 3) {
                    return { value: '3', done: false};
                }
                return { value: '', done: true };
            }
        }
    }
}

for (const i of iterableObj) {
 console.log(i);
}

输出

1
2
3

由于生成器是可迭代的,因此您可以更轻松地实现迭代器。然后,您可以使用for...of循环迭代生成器。例如,

// generator function
function* generatorFunc() {
  
    yield 1;
    yield 2;
    yield 3;
}

const obj = generatorFunc();

// iteration through generator
for (let value of obj) {
    console.log(value);
}

生成器方法

方法 描述
next() 返回yield的值
return() 返回值并终止生成器
throw() 抛出错误并终止生成器

JavaScript return与yield关键字

return关键字 yield关键字
返回值并终止函数。 返回值并暂停函数,但不会终止函数。
在普通函数和生成器函数中都可用。 仅在生成器函数中可用。

带有return的JavaScript生成器函数

您可以在生成器函数中使用return语句。return语句返回值并终止函数(类似于常规函数)。例如,

// generator function
function* generatorFunc() {

    yield 100;

   return 123;

   console.log("2. some code before second yield");
    yield 200;
}

// returns generator object
const generator = generatorFunc();

console.log(generator.next());
console.log(generator.next());
console.log(generator.next());

输出

{value: 100, done: false}
{value: 123, done: true}
{value: undefined, done: true}

在上面的程序中,当遇到return语句时,它将返回值,并且done属性将变为true,函数将终止。因此,return语句之后的next()方法将不返回任何内容。

注意:您也可以使用return()方法而不是return语句,例如在上面的代码中使用generator.return(123);


JavaScript生成器throw方法

您可以使用throw()方法在生成器函数上显式抛出错误。throw()方法的使用会抛出错误并终止函数。例如,

// generator function
function* generatorFunc() {
    yield 100;
    yield 200;
}

// returns generator object
const generator = generatorFunc();

console.log(generator.next());

// throws an error
// terminates the generator
console.log(generator.throw(new Error('Error occurred.')));
console.log(generator.next());

输出

{value: 1, done: false}
Error: Error occurred.

生成器的用途

  • 生成器使我们能够编写更清晰的代码来处理异步任务。
  • 生成器提供了一种更简单的方式来实现迭代器。
  • 生成器仅在需要时执行其代码。
  • 生成器是内存高效的。

生成器是在ES6中引入的。某些浏览器可能不支持生成器的使用。要了解更多信息,请访问JavaScript生成器支持

你觉得这篇文章有帮助吗?

我们的高级学习平台,凭借十多年的经验和数千条反馈创建。

以前所未有的方式学习和提高您的编程技能。

试用 Programiz PRO
  • 交互式课程
  • 证书
  • AI 帮助
  • 2000+ 挑战