function*

Baseline Widely available

This feature is well established and works across many devices and browser versions. It’s been available across browsers since September 2016.

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() 方法被调用时,生成器函数的主体会被执行,直到遇到第一个 yield 表达式,该表达式指定了迭代器要返回的值,或者用 yield* 委托给另一个生成器函数。next() 方法返回一个对象,其 value 属性包含了 yield 表达式的值,done 属性是布尔类型,表示生成器是否已经返回了最后一个值。如果 next() 方法带有参数,那么它会恢复生成器函数的执行,并用参数替换暂停执行的 yield 表达式。

在 JavaScript 中,生成器——尤其是与 Promises 结合使用时——是一种非常强大的异步编程工具,它们解决了回调函数存在的一些的问题,如回调地狱控制反转。然而,通过使用异步函数,我们可以更简单地解决这些问题。

在生成器中执行 return 语句会使生成器结束(即返回的对象的 done 属性将被设置为 true)。如果返回一个值,它将被设置为生成器返回的对象的 value 属性。与 return 语句类似,如果生成器内部抛出错误,生成器也会结束,除非在生成器的代码体内捕获该错误。当生成器结束后,后续 next() 调用不会执行生成器的任何代码,只会返回一个形如 {value: undefined, done: true} 的对象。

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();

// next 的第一次调用从函数的开头开始执行,直到第一个 yield 语句
gen.next(); // 0
gen.next("pretzel"); // 1 pretzel
gen.next("california"); // 2 california
gen.next("mayonnaise"); // 3 mayonnaise

生成器中的返回语句

js
function* yieldAndReturn() {
  yield "产生的值";
  return "返回的值";
  yield "不会被访问到的值";
}

const gen = yieldAndReturn();
console.log(gen.next()); // { value: "产生的值", done: false }
console.log(gen.next()); // { value: "返回的值", 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
const foo = function* () {
  yield 10;
  yield 20;
};

const bar = foo();
console.log(bar.next()); // {value: 10, done: false}

生成器示例

js
function* powers(n) {
  // 无限循环生成
  for (let current = n; ; current *= n) {
    yield current;
  }
}

for (const power of powers(2)) {
  // 控制生成器
  if (power > 32) {
    break;
  }
  console.log(power);
  // 2
  // 4
  // 8
  // 16
  // 32
}

规范

Specification
ECMAScript® 2025 Language Specification
# sec-generator-function-definitions

浏览器兼容性

Report problems with this compatibility data on GitHub
desktopmobileserver
Chrome
Edge
Firefox
Opera
Safari
Chrome Android
Firefox for Android
Opera Android
Safari on iOS
Samsung Internet
WebView Android
WebView on iOS
Deno
Node.js
function* statement
IteratorResult object instead of throwing
Not constructable with new (ES2016)
Trailing comma in parameters

Legend

Tip: you can click/tap on a cell for more information.

Full support
Full support

参见