Javascript 简明教程

JavaScript - Yield Operator

JavaScript Yield Operator

JavaScript 中的 yield 运算符用于异步暂停和恢复生成器函数。在 JavaScript 中, generator 函数是可在执行时暂停或恢复的特殊函数。生成器函数使用“function*”语法定义。 yield 关键字只能在包含它的生成器函数中使用。

The yield operator in JavaScript is used to pause and resume the generator function asynchronously. In JavaScript, generator functions are the special functions that you can pause or resume while executing. The generator functions are defined with the 'function*' syntax. The yield keyword can only be used within the generator function that contains it.

yield 运算符暂停生成器函数的执行,并将其操作数(表达式)返回给生成器的调用方。

The yield operator pauses the execution of generator function and returns its operand (expression) to the generator’s caller.

Syntax

JavaScript 中 yield 运算符的语法如下:

The syntax of the yield operator in JavaScript is as follows −

yield expression;

Paramter

  1. expression − The value to yield from the generator function via the iterator protocol. 'undefined' is yielded, if expression is omitted.

Return value

它返回传递给生成器的 next() 方法的可选值,以恢复其执行。

It returns the optional value passed to the generator’s next() method to resume its execution.

Yield Operator in Genrator Function

为了理解 yield 运算符,让我们先了解生成器函数的工作原理。

To understand the yield operator, let’s understand fist the working of the generator function.

当调用生成器函数时,它会返回一个生成器对象。当调用此生成器对象的 next() 方法时,它会恢复生成器函数的执行。当遇到 yield 表达式时,它会暂停执行,并将 yield 关键字后面的表达式返回给对象的调用方(next() 方法)。

When a generator function is called, it returns a generator object. When the next() method this generator object is called it resumes the execution of the generator function. When a yield expression is encountered, it pauses the execution and returns the expression after yield keyword to the object’s caller (the next() method).

生成器对象的 next() 方法返回一个具有两个属性的迭代器对象: valuedonevalue 是表达式的实际值,而 done 是一个布尔值。如果生成器函数已完全执行,则 done 属性为 true,否则为 false。

The next() method of the generator object returns an iterator object with two properties – value and done. The value is the actual value of the expression and the done is a boolean value. The done property is true if the execution of the generator function is completely executed, else it if false.

下面是带有 yield 关键字(运算符)的生成器函数的完整示例代码。

Below is a complete example code of generator function with yield keyword (operator).

function* test() {
 // function code
 yield expression;
}
const genObj = test();
genObj.next();

在上面的语法中,“function*”用于创建一个名为 test 的生成器函数,yield 关键字用于从函数返回“expression”。

In the above syntax, 'function*' is used to create a generator function named test, and the yield keyword is used to return 'expression' from the function.

调用生成器函数 test,并将返回的生成器对象赋予变量 genObj。当遇到 yield 表达式时,next() 方法会恢复函数的执行并返回迭代器对象。

The generator function test is called and assigned the returned generator object to the variable genObj. The next() method resumes the execution of the function and returns iterator object when encounters yield expression.

让我们执行以下 JavaScript 代码段:

Let’s execute the below JavaScript code snippet –

function* test() {
    console.log("I'm before yield expression");
    yield 20;
}
const genObj = test();
console.log(genObj.next());

请注意,当我们调用 next() 方法时,它会先在控制台显示消息,然后显示迭代器对象。

Notice when we call next() method, it display the message in the console first and then display the iterator object.

I'm before yield expression
{ value: 20, done: false }

Example: Returning a value

在下文中,我们定义了 test() 生成器函数。我们在函数中 3 次使用 yield 运算符分别返回一个数字、一个数组和一个字符串。

In the example below, we have defined the test() generator function. We used the yield operator 3 times in the function to return a number, an array, and a string, respectively.

然后,我们 4 次使用 next() 方法恢复函数的执行。每当控制流查找 yield 运算符时,它会停止执行并返回该值。

After that, we used the next() method four times to resume the execution of the function. Whenever the control flow finds the yield operator, it will stop execution and return the value.

在输出中,你可以观察到它返回包含 yield 运算符的运算对象和布尔值。

In the output, you can observe that it returns the object containing the operand of the yield operator and boolean value.

function* test() {
    yield 20;
    yield [1,2,3];
    yield "Hello World";
}
let res = test();
console.log(res.next());
console.log(res.next());
console.log(res.next());
console.log(res.next());

Output

{ value: 20, done: false }
{ value: [ 1, 2, 3 ], done: false }
{ value: 'Hello World', done: false }
{ value: undefined, done: true }

Example: Returning undefined

当我们在 yield 关键字后面省略表达式时,它将返回未定义。

When we omit the expression following the yield keyword, it will return undefined.

function* test() {
    yield;
}

let res = test();
console.log(res.next());
console.log(res.next());

Output

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

Example: Passing a value to the next() method

我们还可以将值传递给 next() 方法。在下面的示例中,我们已经将 30 传递给第二个 next() 方法。它将 yield 评估为 30。变量 result 被赋值 yield 的值为 30。

We can also pass a value to the next() method. In the below example, we have passed 30 to the second next() method. It evaluates yield to 30. The variable result is assigned the value of yield which is evaluated as 30.

function* test() {
    let result = yield 20;
    console.log("default value paased to next() method " + result);
}

let res = test();
console.log(res.next());
console.log(res.next(30));

Output

{ value: 20, done: false }
default value paased to next() method 30
{ value: undefined, done: true }

Example

在下面的代码中,我们使用了循环,在每个操作中,我们使用 yield 运算符停止函数的执行。之后,我们使用 next() 方法启动生成器函数的执行。

In the below code, we used the loop, and in each operation, we stop the execution of the function using the yield operator. Afterward, we use the next() method to start the execution of the generator function.

// Generator function
function* test() {
    for (let p = 0; p < 6; p += 2) {
        yield p;
    }
}
let res = test();
console.log(res.next());
console.log(res.next());
console.log(res.next());
console.log(res.next());

Output

{ value: 0, done: false }
{ value: 2, done: false }
{ value: 4, done: false }
{ value: undefined, done: true }

在实时开发中,程序员将“yield”运算符用于异步操作、延迟评估、任务调度、遍历大型数据集、创建自定义迭代器等。

In real-time development, programmers use the 'yield' operator for asynchronous operations, lazy evaluations, task scheduling, iterating through large datasets, creating custom iterators, etc.