function*
function* 声明会创建一个新的生成器函数到给定名称的绑定。生成器函数可以暂停执行,之后再恢复执行,它的上下文(变量绑定)会在多次重新进入时保存下来。
你也可以使用function* 表达式定义生成器函数。
试一试
function* generator(i) {
yield i;
yield i + 10;
}
const gen = generator(10);
console.log(gen.next().value);
// Expected output: 10
console.log(gen.next().value);
// Expected output: 20
语法
function* name(param0) {
statements
}
function* name(param0, param1) {
statements
}
function* name(param0, param1, /* …, */ paramN) {
statements
}
注意:生成器函数没有对应的箭头函数。
注意:function 和 * 是独立的词法单元,因此它们可以被空格或行终止符分隔。
参数
name-
函数名称。
param可选-
函数形式参数的名称。有关参数的语法,请参阅函数参考。
statements可选-
构成函数体的语句。
描述
function* 声明创建一个 GeneratorFunction 对象。每次调用生成器函数时,它都会返回一个新的 Generator 对象,该对象符合 迭代器协议。生成器函数的执行会在某个位置暂停,最初是在函数体的最开始。生成器函数可以被多次调用以同时创建多个生成器;每个生成器都维护自己的生成器函数执行上下文,并且可以独立地执行。
生成器允许双向控制流:控制流可以在生成器函数(被调用者)及其调用者之间根据双方意愿多次传递。控制流可以通过调用生成器的方法从调用者流向被调用者:next()、throw() 和 return()。控制流可以通过使用 return 或 throw 或执行所有语句正常退出函数,或者通过使用 yield 和 yield* 表达式从被调用者流向调用者。
当调用生成器的 next() 方法时,生成器函数的函数体将执行,直到发生以下情况之一:
- 一个
yield表达式。在这种情况下,next()方法返回一个对象,该对象具有一个包含生成值的value属性和一个始终为false的done属性。下次调用next()时,yield表达式将评估为传递给next()的值。 - 一个
yield*,委托给另一个迭代器。在这种情况下,此调用以及后续对生成器进行的任何next()调用都与对委托迭代器调用next()相同,直到委托迭代器完成。 - 一个
return语句(未被try...catch...finally捕获),或控制流的结束(这意味着隐式return undefined)。在这种情况下,生成器已完成,next()方法返回一个对象,该对象具有一个包含返回值的value属性和一个始终为true的done属性。任何进一步的next()调用都不会产生任何效果,并且始终返回{ value: undefined, done: true }。 - 函数内部抛出的错误,通过
throw语句或未处理的异常。next()方法抛出该错误,生成器完成。任何进一步的next()调用都不会产生任何效果,并且始终返回{ value: undefined, done: true }。
当调用生成器的 throw() 方法时,其作用就像在生成器主体当前暂停的位置插入了一个 throw 语句。类似地,当调用生成器的 return() 方法时,其作用就像在生成器主体当前暂停的位置插入了一个 return 语句。除非生成器函数通过 try...catch...finally 捕获了完成,否则这两种方法通常都会终止生成器。
生成器曾经是异步编程的一种范式,通过实现控制反转来避免回调地狱。如今,这种用例已通过更简单的异步函数模型和Promise对象解决。然而,生成器仍然对许多其他任务很有用,例如以简单明了的方式定义迭代器。
function* 声明的行为类似于 function 声明——它们被提升到其作用域的顶部,可以在其作用域中的任何位置调用,并且只能在特定上下文中重新声明。
示例
基本示例
function* idMaker() {
let index = 0;
while (true) {
yield index++;
}
}
const gen = idMaker();
console.log(gen.next().value); // 0
console.log(gen.next().value); // 1
console.log(gen.next().value); // 2
console.log(gen.next().value); // 3
// …
使用 yield* 的示例
function* anotherGenerator(i) {
yield i + 1;
yield i + 2;
yield i + 3;
}
function* generator(i) {
yield i;
yield* anotherGenerator(i);
yield i + 10;
}
const gen = generator(10);
console.log(gen.next().value); // 10
console.log(gen.next().value); // 11
console.log(gen.next().value); // 12
console.log(gen.next().value); // 13
console.log(gen.next().value); // 20
向生成器传递参数
function* logGenerator() {
console.log(0);
console.log(1, yield);
console.log(2, yield);
console.log(3, yield);
}
const gen = logGenerator();
// the first call of next executes from the start of the function
// until the first yield statement
gen.next(); // 0
gen.next("pretzel"); // 1 pretzel
gen.next("california"); // 2 california
gen.next("mayonnaise"); // 3 mayonnaise
生成器中的 return 语句
function* yieldAndReturn() {
yield "Y";
return "R";
yield "unreachable";
}
const gen = yieldAndReturn();
console.log(gen.next()); // { value: "Y", done: false }
console.log(gen.next()); // { value: "R", done: true }
console.log(gen.next()); // { value: undefined, done: true }
作为对象属性的生成器
const someObj = {
*generator() {
yield "a";
yield "b";
},
};
const gen = someObj.generator();
console.log(gen.next()); // { value: 'a', done: false }
console.log(gen.next()); // { value: 'b', done: false }
console.log(gen.next()); // { value: undefined, done: true }
作为对象方法的生成器
class Foo {
*generator() {
yield 1;
yield 2;
yield 3;
}
}
const f = new Foo();
const gen = f.generator();
console.log(gen.next()); // { value: 1, done: false }
console.log(gen.next()); // { value: 2, done: false }
console.log(gen.next()); // { value: 3, done: false }
console.log(gen.next()); // { value: undefined, done: true }
作为计算属性的生成器
class Foo {
*[Symbol.iterator]() {
yield 1;
yield 2;
}
}
const SomeObj = {
*[Symbol.iterator]() {
yield "a";
yield "b";
},
};
console.log(Array.from(new Foo())); // [ 1, 2 ]
console.log(Array.from(SomeObj)); // [ 'a', 'b' ]
生成器不可构造
function* f() {}
const obj = new f(); // throws "TypeError: f is not a constructor
生成器示例
function* powers(n) {
// Endless loop to generate
for (let current = n; ; current *= n) {
yield current;
}
}
for (const power of powers(2)) {
// Controlling generator
if (power > 32) {
break;
}
console.log(power);
// 2
// 4
// 8
// 16
// 32
}
规范
| 规范 |
|---|
| ECMAScript® 2026 语言规范 # sec-generator-function-definitions |
浏览器兼容性
加载中…
另见
- 函数指南
- 迭代器和生成器指南
- 函数
GeneratorFunctionfunction*表达式functionasync functionasync function*- 迭代协议
yieldyield*Generator- GitHub 上的 Regenerator
- Promises 和 Generators:控制流乌托邦 — Forbes Lindesay 在 JSConf 上的演讲 (2013)
- GitHub 上的 Task.js
- 你不知道的 JS:异步与性能,第 4 章:生成器 — Kyle Simpson