如何用JavaScript创建生成器函数?

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

生成器函数是JavaScript中一类特殊的函数,它可以通过yield关键字暂停执行,在需要的时候再恢复执行,非常适合处理需要分步执行或者惰性计算的场景。下面我们就一步步学习如何创建和使用生成器函数。

如何用JavaScript创建生成器函数?

生成器函数的基本定义方式

生成器函数和普通函数的区别是在function关键字后面加一个星号*,函数内部可以使用yield关键字来暂停执行,返回中间结果。定义生成器函数的语法如下:

// 基本生成器函数定义
function* simpleGenerator() {
  yield '第一个值';
  yield '第二个值';
  yield '第三个值';
  return '结束值';
}

调用生成器函数的时候,不会立刻执行函数内部的代码,而是会返回一个生成器对象,这个对象符合迭代器协议,可以通过next()方法来逐步执行函数内部的逻辑。

yield关键字的作用

yield是生成器函数的核心关键字,它的作用是暂停函数的执行,并且把后面跟着的值作为当前next()调用的返回值。每次调用生成器对象的next()方法,函数会从上次暂停的位置继续执行,直到遇到下一个yield或者函数结束。

我们可以通过下面的示例来观察执行过程:

function* demoGenerator() {
  console.log('开始执行');
  const result1 = yield 10;
  console.log('第一次恢复执行,接收到的值:', result1);
  const result2 = yield 20;
  console.log('第二次恢复执行,接收到的值:', result2);
  return 30;
}

const gen = demoGenerator();
// 第一次调用next,执行到第一个yield暂停,返回{value:10, done:false}
console.log(gen.next()); 
// 第二次调用next,传入参数作为上一个yield的返回值,执行到第二个yield暂停
console.log(gen.next('传入值1')); 
// 第三次调用next,传入参数作为第二个yield的返回值,执行到return结束
console.log(gen.next('传入值2')); 

上面的代码执行后,输出结果如下:

开始执行
{ value: 10, done: false }
第一次恢复执行,接收到的值: 传入值1
{ value: 20, done: false }
第二次恢复执行,接收到的值: 传入值2
{ value: 30, done: true }

生成器对象的迭代器特性

生成器对象本身是可迭代的,所以可以直接用for...of循环来遍历生成器产生的所有值,不过要注意,for...of只会遍历yield返回的值,不会遍历return返回的最终值。

function* numberGenerator() {
  yield 1;
  yield 2;
  yield 3;
  return 4;
}

const gen = numberGenerator();
for (const num of gen) {
  console.log(num);
}
// 输出:1 2 3

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

1. 实现自定义迭代器

如果我们需要让一个对象可以被迭代,除了实现Symbol.iterator方法,也可以用生成器函数来简化实现:

const customObj = {
  data: [10, 20, 30, 40],
  *[Symbol.iterator]() {
    for (const item of this.data) {
      yield item * 2;
    }
  }
};

for (const val of customObj) {
  console.log(val);
}
// 输出:20 40 60 80

2. 处理异步流程

虽然现在async/await更常用,但生成器函数也可以配合执行器来处理异步逻辑,实现类似同步代码的写法:

function* asyncTaskGenerator() {
  const res1 = yield new Promise(resolve => setTimeout(() => resolve('第一步结果'), 1000));
  console.log(res1);
  const res2 = yield new Promise(resolve => setTimeout(() => resolve('第二步结果'), 1000));
  console.log(res2);
  return '全部完成';
}

// 简单的生成器执行器
function runGenerator(gen) {
  const generator = gen();
  function handle(result) {
    if (result.done) return result.value;
    result.value.then(data => {
      handle(generator.next(data));
    });
  }
  handle(generator.next());
}

runGenerator(asyncTaskGenerator);
// 1秒后输出:第一步结果,再1秒后输出:第二步结果

注意事项

  • 生成器函数内部的this指向和普通函数一致,但是如果生成器函数作为对象的方法,需要注意调用时的上下文。
  • yield关键字只能在生成器函数内部使用,在普通函数中使用会报错。
  • 生成器对象的next()方法可以传入参数,这个参数会成为上一个yield表达式的返回值。
  • 生成器函数执行完毕后,再次调用next()会返回{value: undefined, done: true}

JavaScript生成器函数Generatoryield迭代器修改时间:2026-05-29 23:17:59

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