当前位置: 首页 > news >正文

js中的生成器函数

JavaScript 的生成器函数(Generator Function)是一种特殊的函数,它可以暂停执行恢复执行,并可以产出(yield)多个值(而普通函数只能返回单个值)。

基本概念

1. 创建生成器函数

function* generatorFunction() {yield '第一个值';yield '第二个值';yield '第三个值';
}

注意:使用 function* 声明(星号可以放在 function 后面或函数名前)

2. 基本使用

function* simpleGenerator() {yield 1;yield 2;yield 3;
}const gen = simpleGenerator();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 }

主要特性

1. 暂停和恢复执行

function* counter() {console.log('开始');yield '暂停点1';console.log('继续执行');yield '暂停点2';return '结束';
}const gen = counter();
console.log(gen.next()); // 开始 → { value: '暂停点1', done: false }
console.log(gen.next()); // 继续执行 → { value: '暂停点2', done: false }
console.log(gen.next()); // { value: '结束', done: true }

2. 双向通信

可以向生成器传递值:

function* twoWayCommunication() {const name = yield '你的名字是什么?';const age = yield `你好 ${name},你多大了?`;return `${name} 今年 ${age} 岁`;
}const gen = twoWayCommunication();
console.log(gen.next());    // { value: '你的名字是什么?', done: false }
console.log(gen.next('小明')); // { value: '你好 小明,你多大了?', done: false }
console.log(gen.next(25));  // { value: '小明 今年 25 岁', done: true }

3. 无限序列生成

function* infiniteNumbers() {let n = 0;while (true) {yield n++;}
}const numbers = infiniteNumbers();
console.log(numbers.next().value); // 0
console.log(numbers.next().value); // 1
console.log(numbers.next().value); // 2
// 可以无限调用...

实用场景

1. 惰性计算

function* take(n, generator) {for (let i = 0; i < n; i++) {yield generator.next().value;}
}function* fibonacci() {let [prev, curr] = [0, 1];while (true) {yield curr;[prev, curr] = [curr, prev + curr];}
}// 只获取前10个斐波那契数
const firstTen = [...take(10, fibonacci())];
console.log(firstTen); // [1, 1, 2, 3, 5, 8, 13, 21, 34, 55]

2. 异步操作控制(async/await 出现前)

function asyncTask(time) {return new Promise(resolve => setTimeout(() => resolve(`完成 ${time}ms`), time));
}function* asyncGenerator() {const result1 = yield asyncTask(1000);console.log(result1);const result2 = yield asyncTask(500);console.log(result2);
}// 手动执行生成器
function run(generator) {const gen = generator();function handle(result) {if (result.done) return Promise.resolve(result.value);return Promise.resolve(result.value).then(data => handle(gen.next(data))).catch(err => gen.throw(err));}return handle(gen.next());
}run(asyncGenerator);

3. 状态机实现

function* stateMachine() {let state = '开始';while (true) {const action = yield state;if (action === '下一步' && state === '开始') {state = '进行中';} else if (action === '下一步' && state === '进行中') {state = '完成';} else if (action === '重置') {state = '开始';}}
}const machine = stateMachine();
console.log(machine.next().value); // '开始'
console.log(machine.next('下一步').value); // '进行中'
console.log(machine.next('下一步').value); // '完成'
console.log(machine.next('重置').value); // '开始'

4. 可迭代对象

生成器函数返回的是可迭代对象:

function* range(start, end) {for (let i = start; i <= end; i++) {yield i;}
}// 可以直接用于 for...of
for (let num of range(1, 5)) {console.log(num); // 1, 2, 3, 4, 5
}// 或者使用扩展运算符
const numbers = [...range(1, 3)];
console.log(numbers); // [1, 2, 3]

方法总结

生成器对象的方法:

function* sample() {yield 1;yield 2;yield 3;
}const gen = sample();// 1. next() - 获取下一个值
gen.next();// 2. return() - 结束生成器
gen.return('提前结束');// 3. throw() - 向生成器抛出错误
gen.throw(new Error('出错了'));

注意事项

  1. 箭头函数不能作为生成器(箭头函数没有 function 关键字)
  2. 生成器函数调用时不立即执行,而是返回一个生成器对象
  3. 生成器对象既是迭代器也是可迭代对象
  4. 在类中也可以使用生成器方法:
    class MyClass {*generatorMethod() {yield 'hello';}
    }
    

生成器函数提供了强大的控制流管理能力,虽然在现代 JavaScript 中很多场景已被 async/await 替代,但在处理复杂的状态机、惰性计算、数据流处理等方面仍然非常有用。

http://www.jsqmd.com/news/351110/

相关文章:

  • SAP核心模块单据关系及关键数据表详解
  • 微信小程序Python-uniapp基于Android的全民健身App设计与实现
  • 地平线征程 6 工具链入门教程 | 征程 6B 计算平台部署指南
  • 微信小程序Python-uniapp 小区果蔬商城
  • Vibe Coding 与 LangChain、LangGraph 的协同进化
  • 代码生成超越 GPT-4:DeepSeek-V4 编程任务实战与 2026 开发者效率提升指南
  • 微信小程序Python-uniapp 游戏攻略系统 逃跑吧!少年的游戏角色介绍系统
  • 【毕设】基于人脸识别的实验室智能门禁系统的设计与实现
  • 微信小程序Python-uniapp 演唱会售票系统
  • 2026低成本训练趋势:DeepSeek复刻V4训练管线,低成本实现模型微调实战
  • 大数据领域Zookeeper的会话管理机制研究
  • AI原生应用架构设计:何时使用模型蒸馏?
  • 微信小程序Python-uniapp 智能包裹配送服务管理系统
  • 图解网络26 - 指南
  • 微信小程序Python-uniapp 校园财递通快递代取系统的设计与实现
  • 微信小程序Python-uniapp 消防知识学习平台系统
  • DeepSeek总结的PostgreSQL解码GIF文件SQL移植到DuckDB的性能优化方法
  • 基于Spring Boot的企业采购管理系统的设计与实现
  • 如何通过管理中心发布Teams应用
  • holiday 2026.02.06
  • 比较好的入户门品牌有哪些?2026十大品牌综合实力深度评测解析 - 匠言榜单
  • 数据行业六大岗位详解+AI大模型入门到进阶学习路线_AI大模型时代下的数据行业
  • AI大模型高薪职位全攻略+学习资料包,助程序员薪资翻倍,从入门到实战_AI大模型岗位薪资揭秘:2026大模型岗位薪资
  • 《CF960F Pathwalks》
  • Kafka生产者详解(下):数据去重(幂等性)与数据有序 - 指南
  • 2025年主流大语言模型深度对比:GPT-4o、Claude 3.7、DeepSeek-R1 与 Qwen2.5
  • 0欧电阻作用
  • 电商大模型应用:知识图谱构建实战指南,如何基于⼤模型构建电商知识图谱?
  • Java做人工智能?JBoltAI带你轻松入门AI应用开发
  • CANN -acl_benchmark-赋能AIGC:严谨测评,铸就高性能生成式AI服务