在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}。

向生成器函数传递参数
您还可以向生成器函数传递参数。例如,
// 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生成器支持。