什么是JavaScript中的生成器函数?

来源:IPIPP.com作者:头衔:全栈工程师
导读:本期聚焦于小伙伴创作的《什么是JavaScript中的生成器函数?》,敬请观看详情,探索知识的价值。以下视频、文章将为您系统阐述其核心内容与价值。如果您觉得《什么是JavaScript中的生成器函数?》有用,将其分享出去将是对创作者最好的鼓励。

JavaScript中的生成器函数是ES6新增的一种特殊函数类型,它可以通过yield关键字暂停函数执行,之后还能从暂停的位置恢复执行,和普通函数的一次性执行完毕有本质区别。生成器函数执行后不会直接返回结果,而是返回一个生成器对象,这个对象符合迭代器协议,可以通过next方法逐步获取函数运行过程中产出的值。

什么是JavaScript中的生成器函数?

生成器函数的基本语法

生成器函数的定义和普通函数不同,需要在function关键字后面加一个星号*,函数内部可以使用yield关键字来暂停执行并产出值。下面是一个最简单的生成器函数示例:

// 定义一个生成器函数
function* simpleGenerator() {
  yield 1;
  yield 2;
  yield 3;
}

// 执行生成器函数,得到生成器对象
const gen = simpleGenerator();

// 调用next方法获取值
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 }

从上面的例子可以看到,每次调用生成器对象的next方法,函数就会执行到下一个yield位置,返回一个包含value和done属性的对象。value是yield后面跟的值,done表示生成器是否已经执行完毕。

生成器函数的执行流程详解

生成器函数的执行过程可以分为几个关键步骤:

  • 当调用生成器函数时,函数体不会立即执行,而是返回一个生成器对象。
  • 第一次调用生成器对象的next方法时,函数开始执行,直到遇到第一个yield表达式,暂停执行,将yield后面的值作为返回对象的value。
  • 后续每次调用next方法,函数会从暂停的位置继续执行,直到遇到下一个yield或者函数结束。
  • 如果函数执行完毕,没有更多的yield,那么返回的对象的done属性会变成true,value是函数最终的返回值,如果没有返回值就是undefined。

我们还可以通过next方法给生成器函数传值,这个传递的值会成为上一次yield表达式的返回值,示例如下:

function* passValueGenerator() {
  const a = yield '请输入第一个值';
  const b = yield '请输入第二个值';
  return a + b;
}

const gen2 = passValueGenerator();
console.log(gen2.next()); // { value: '请输入第一个值', done: false }
// 传递10给上一次的yield,赋值给a
console.log(gen2.next(10)); // { value: '请输入第二个值', done: false }
// 传递20给上一次的yield,赋值给b
console.log(gen2.next(20)); // { value: 30, done: true }

生成器对象与迭代器协议

生成器对象本身是符合迭代器协议的对象,所以它可以直接用于for...of循环,这是生成器函数最常见的使用场景之一。因为for...of循环会自动调用迭代器的next方法,直到done为true。示例如下:

function* rangeGenerator(start, end) {
  let current = start;
  while (current <= end) {
    yield current;
    current++;
  }
}

// 使用for...of遍历生成器对象
for (const num of rangeGenerator(1, 5)) {
  console.log(num); // 依次输出1、2、3、4、5
}

从上面的例子可以看到,我们不需要手动调用next方法,for...of循环会自动处理迭代过程,这让生成器函数非常适合用来创建自定义的迭代逻辑。

生成器函数的常见应用场景

自定义可迭代对象

当我们想要让一个对象可以被for...of遍历时,只需要给这个对象添加Symbol.iterator方法,而生成器函数是实现这个方法最简洁的方式。示例如下:

const customIterable = {
  data: [10, 20, 30],
  // 使用生成器函数实现Symbol.iterator方法
  [Symbol.iterator]: function* () {
    for (const item of this.data) {
      yield item * 2;
    }
  }
};

for (const val of customIterable) {
  console.log(val); // 依次输出20、40、60
}

简化异步流程控制

在早期JavaScript异步编程中,生成器函数常被用来配合执行器函数简化异步代码,避免回调嵌套。虽然现在async/await已经成为主流,但理解生成器在异步中的应用有助于掌握异步编程的演进历程。下面是一个简单的异步生成器示例:

// 模拟异步请求
function mockAsyncRequest(url) {
  return new Promise(resolve => {
    setTimeout(() => {
      resolve(`请求${url}的结果`);
    }, 1000);
  });
}

function* asyncFlowGenerator() {
  const res1 = yield mockAsyncRequest('api/data1');
  console.log(res1);
  const res2 = yield mockAsyncRequest('api/data2');
  console.log(res2);
  return '所有请求完成';
}

// 简单的生成器执行器
function runGenerator(gen) {
  const generator = gen();
  function handle(result) {
    if (result.done) {
      return result.value;
    }
    // 如果yield后面是Promise,等待它完成后再继续执行
    if (result.value.then) {
      result.value.then(data => {
        handle(generator.next(data));
      });
    } else {
      handle(generator.next(result.value));
    }
  }
  handle(generator.next());
}

runGenerator(asyncFlowGenerator);
// 1秒后输出请求api/data1的结果,再1秒后输出请求api/data2的结果,最后输出所有请求完成

生成器函数的注意事项

  • 生成器函数内部的yield关键字只能在生成器函数内部使用,不能在嵌套的普通函数中使用。
  • 生成器函数执行后返回的生成器对象,遍历完之后就无法再次遍历,如果需要重新遍历,需要重新执行生成器函数获取新的生成器对象。
  • yield表达式本身没有返回值,或者说返回值是undefined,除非我们通过next方法向生成器传递参数,这个参数才会成为上一个yield的返回值。

生成器函数作为JavaScript中比较特殊的函数类型,虽然日常开发中直接用到的场景不如普通函数多,但在实现自定义迭代逻辑、理解异步编程原理等方面都有重要的价值,掌握它可以帮助开发者写出更灵活、更易维护的代码。

generator迭代器yieldnext修改时间:2026-06-03 00:24:19

免责声明:​ 已尽一切努力确保本网站所含信息的准确性。网站内容多为原创整理与精心编撰,观点力求客观中立。本站旨在免费分享,内容仅供个人学习、研究或参考使用。若引用了第三方作品,版权归原作者所有。如内容涉及您的权益,请联系我们处理。
内容垂直聚焦
专注技术核心技术栏目,确保每篇文章深度聚焦于实用技能。从代码技巧到架构设计,为用户提供无干扰的纯技术知识沉淀,精准满足专业提升需求。
知识结构清晰
覆盖从开发到部署的全链路。AI、前端、编程、数据库、服务器、建站、系统层层递进,构建清晰学习路径,帮助用户系统化掌握开发与运维所需的核心技术。
深度技术解析
拒绝泛泛而谈,深入技术细节与实践难点。无论是数据库优化还是服务器配置,均结合真实场景与代码示例进行剖析,致力于提供可直接应用于工作的解决方案。
专业领域覆盖
精准对应开发生命周期。从前端界面到后端编程,从数据库操作到服务器运维,形成完整闭环,一站式满足全栈工程师和运维人员的技术需求。
即学即用高效
内容强调实操性,步骤清晰、代码完整。用户可根据教程直接复现和应用于自身项目,显著缩短从学习到实践的距离,快速解决开发中的具体问题。
持续更新保障
专注既定技术方向进行长期、稳定的内容输出。确保各栏目技术文章持续更新迭代,紧跟主流技术发展趋势,为用户提供经久不衰的学习价值。