生成器函数概念与用法详解
生成器函数(Generator Function)是 JavaScript 中一种特殊的函数,它允许你逐步执行函数体,并在过程中多次返回(或“产出”)值,而不是一次性执行完毕。这种特性使得它非常适合处理异步操作、创建迭代器和处理大数据集等场景。
核心概念
- 语法标记
使用 function* 声明(注意星号 * 的位置):
function* myGenerator() {// 函数体
}
- yield 关键字
在函数内部用 yield 暂停执行并返回一个值:
function* numberGenerator() {yield 1;yield 2;yield 3;
}
- 返回生成器对象
调用生成器函数时,不会立即执行函数体,而是返回一个生成器对象(Generator Object)。该对象符合迭代协议,可通过 .next() 方法逐步执行:
const gen = numberGenerator();
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,节省内存 |
双向通信 | 可通过 .next(value) 向生成器内部传递值(作为 yield 的返回值) |
错误处理 | 用 .throw(error) 向生成器内部抛出错误,可在函数内用 try…catch 捕获 |
提前终止 | 用 .return() 强制结束生成器 |
常见用途
- 创建自定义迭代器
function* range(start, end) {for (let i = start; i <= end; i++) {yield i;}
}for (const num of range(1, 5)) {console.log(num); // 依次输出 1, 2, 3, 4, 5
}
- 简化异步流程(类似 async/await)
function* fetchUser() {const user = yield fetch('/api/user'); // 暂停等待异步操作const posts = yield fetch(`/api/posts?userId=${user.id}`);return posts;
}// 手动执行(实际可用 co 等库自动处理)
const gen = fetchUser();
gen.next().value.then(user => gen.next(user).value).then(posts => console.log(posts));
- 无限数据流
function* infiniteSequence() {let i = 0;while (true) {yield i++;}
}const gen = infiniteSequence();
console.log(gen.next().value); // 0
console.log(gen.next().value); // 1
// ...可无限调用
- 状态机实现
function* trafficLight() {while (true) {yield '🟢'; // 绿灯yield '🟡'; // 黄灯yield '🔴'; // 红灯}
}const light = trafficLight();
light.next().value; // 🟢
light.next().value; // 🟡
与普通函数的区别
特性 | 普通函数 | 生成器函数 |
---|---|---|
执行方式 | 一次性执行到底 | 可暂停/恢复 |
返回值 | 单一值(或 undefined) | 返回生成器对象(可迭代) |
关键字 | return | yield(多次返回) |
内存占用 | 一次性分配所有资源 | 按需生成值,节省内存 |
浏览器兼容性
- 现代浏览器和 Node.js 均支持(ES2015+ 标准)
- 旧环境需通过 Babel 等工具转译
生成器函数为 JavaScript 提供了更灵活的流程控制能力,是处理异步迭代、大型数据流和复杂状态逻辑的强大工具。