function*

Baseline 已广泛支持

此特性已非常成熟,可在多种设备和浏览器版本上使用。自 ⁨2016 年 9 月⁩以来,它已在各大浏览器中可用。

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

语法

js
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()。控制流可以通过使用 returnthrow 或执行所有语句正常退出函数,或者通过使用 yieldyield* 表达式从被调用者流向调用者。

当调用生成器的 next() 方法时,生成器函数的函数体将执行,直到发生以下情况之一:

  • 一个 yield 表达式。在这种情况下,next() 方法返回一个对象,该对象具有一个包含生成值的 value 属性和一个始终为 falsedone 属性。下次调用 next() 时,yield 表达式将评估为传递给 next() 的值。
  • 一个 yield*,委托给另一个迭代器。在这种情况下,此调用以及后续对生成器进行的任何 next() 调用都与对委托迭代器调用 next() 相同,直到委托迭代器完成。
  • 一个 return 语句(未被 try...catch...finally 捕获),或控制流的结束(这意味着隐式 return undefined)。在这种情况下,生成器已完成,next() 方法返回一个对象,该对象具有一个包含返回值的 value 属性和一个始终为 truedone 属性。任何进一步的 next() 调用都不会产生任何效果,并且始终返回 { value: undefined, done: true }
  • 函数内部抛出的错误,通过 throw 语句或未处理的异常。next() 方法抛出该错误,生成器完成。任何进一步的 next() 调用都不会产生任何效果,并且始终返回 { value: undefined, done: true }

当调用生成器的 throw() 方法时,其作用就像在生成器主体当前暂停的位置插入了一个 throw 语句。类似地,当调用生成器的 return() 方法时,其作用就像在生成器主体当前暂停的位置插入了一个 return 语句。除非生成器函数通过 try...catch...finally 捕获了完成,否则这两种方法通常都会终止生成器。

生成器曾经是异步编程的一种范式,通过实现控制反转来避免回调地狱。如今,这种用例已通过更简单的异步函数模型和Promise对象解决。然而,生成器仍然对许多其他任务很有用,例如以简单明了的方式定义迭代器

function* 声明的行为类似于 function 声明——它们被提升到其作用域的顶部,可以在其作用域中的任何位置调用,并且只能在特定上下文中重新声明。

示例

基本示例

js
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* 的示例

js
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

向生成器传递参数

js
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 语句

js
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 }

作为对象属性的生成器

js
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 }

作为对象方法的生成器

js
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 }

作为计算属性的生成器

js
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' ]

生成器不可构造

js
function* f() {}
const obj = new f(); // throws "TypeError: f is not a constructor

生成器示例

js
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

浏览器兼容性

另见