JavaScript 生成器 Generator 函数全面总结

以下回答主要由 Deepseek AI 生成,经博主本人审核和增删整理,如有错漏请评论区反馈。

JavaScript Generator 函数全面总结

Generator 基础概念

项目 描述 示例
定义 能暂停和恢复执行的函数,使用 function* 声明 function* gen() { yield 1; }
yield 关键字 暂停函数执行并返回一个值 yield expression;
next() 方法 恢复函数执行,返回 {value, done} 对象 gen.next()
返回值 返回一个 Generator 对象(可迭代对象) 符合迭代协议和迭代器协议

Generator 函数声明方式

方式 语法 说明
函数声明 function* generator() { yield 1; } 标准的声明方式
函数表达式 const generator = function*() { yield 1; } 赋值给变量
对象方法 const obj = { *generator() { yield 1; } } 方法简写形式
类方法 class A { *generator() { yield 1; } } 类中的生成器方法

Generator 对象方法

方法 参数 返回值 作用
next() value (可选) { value: any, done: boolean } 恢复执行,直到下一个 yield
return() value (可选) { value, done: true } 立即终止生成器
throw() error { value, done } 向生成器抛出错误

yield 表达式行为

场景 行为 示例
基本 yield 暂停执行,返回右侧表达式的值 yield 1{value: 1, done: false}
yield 接收值 通过 next() 参数向生成器传递值 const input = yield;
yield* 委托给另一个生成器或可迭代对象 yield* [1, 2, 3]
return 语句 终止生成器,done 变为 true return 'end'{value: 'end', done: true}

执行流程控制

步骤 代码示例 执行结果
创建生成器 const gen = generator(); 生成器对象,未开始执行
第一次 next() gen.next() 执行到第一个 yield,返回 yield 的值
传递值 gen.next('hello') 恢复执行,'hello' 赋给上一个 yield 表达式
最终完成 gen.next() 返回 {value: undefined, done: true}

实际应用场景

场景 代码示例 优势
惰性求值 function* fibonacci() { let [a, b] = [0, 1]; while(true) { yield a; [a, b] = [b, a + b]; } } 按需生成,无限序列
状态机 function* stateMachine() { while(true) { yield 'state1'; yield 'state2'; } } 清晰的状态管理
异步控制流 function* asyncFlow() { const user = yield fetchUser(); const posts = yield fetchPosts(user.id); } 类似同步的异步编程
数据流处理 function* pipeline(data) { data = yield* transform1(data); data = yield* transform2(data); return data; } 可组合的数据处理

使用生成器的情况

场景 理由 示例
惰性求值 按需生成值,节省内存 无限序列、大数据集
状态管理 维护复杂状态机 游戏状态、工作流
数据流处理 构建处理管道 数据转换流水线
自定义迭代 实现复杂的迭代逻辑 树遍历、特殊数据结构

生成器的独特应用场景

1. 惰性计算和无限序列

javascript 复制代码
// 生成器:无限序列 - async/await 无法替代
function* fibonacci() {
    let [a, b] = [0, 1];
    while (true) {
        yield a;
        [a, b] = [b, a + b];
    }
}

const fib = fibonacci();
console.log(fib.next().value); // 0
console.log(fib.next().value); // 1
console.log(fib.next().value); // 1
console.log(fib.next().value); // 2
// 可以无限继续...

2. 状态机和协程

javascript 复制代码
// 生成器:状态机 - async/await 无法替代
function* trafficLight() {
    while (true) {
        yield 'red';
        yield 'green';
        yield 'yellow';
    }
}

const light = trafficLight();
console.log(light.next().value); // 'red'
console.log(next().value); // 'green'
console.log(light.next().value); // 'yellow'
console.log(light.next().value); // 'red' (循环)

3. 数据流处理管道

javascript 复制代码
// 生成器:数据处理管道
function* numbers() {
    let i = 0;
    while (i < 5) {
        yield i++;
    }
}

function* double(iterable) {
    for (const item of iterable) {
        yield item * 2;
    }
}

function* filterEven(iterable) {
    for (const item of iterable) {
        if (item % 2 === 0) {
            yield item;
        }
    }
}

// 组合生成器
const pipeline = filterEven(double(numbers()));
console.log([...pipeline]); // [0, 4, 8]

Generator 与迭代协议

特性 描述 示例
可迭代对象 Generator 对象实现了 [Symbol.iterator] for (const value of gen())
迭代器协议 有 next() 方法,返回 {value, done} 符合迭代器标准
yield* 委托 迭代另一个可迭代对象 yield* [1, 2, 3]
提前终止 return() 方法实现可选的迭代器方法 gen.return('stop')

错误处理

方式 语法 行为
内部 try/catch try { yield risky(); } catch(e) { } 捕获生成器内部的错误
throw() 方法 gen.throw(new Error()) 从外部向生成器抛出错误
生成器内部抛出 throw new Error() 错误会传播到外部

Generator 与异步编程

模式 代码示例 说明
传统回调 function* asyncGen() { const data = yield fs.readFile('file', cb); } 需要外部运行器
Promise 配合 function* asyncGen() { const data = yield fetch(url); return data.json(); } 需要自动执行器
async/await 关系 async/await 是 Generator + Promise 的语法糖 更简洁的异步解决方案

常用工具模式

基础运行器

javascript 复制代码
function runGenerator(genFunc) {
    const gen = genFunc();
    
    function step(nextValue) {
        const result = gen.next(nextValue);
        if (result.done) return Promise.resolve(result.value);
        
        return Promise.resolve(result.value).then(step, err => gen.throw(err));
    }
    
    return step();
}

状态机示例

javascript 复制代码
function* trafficLight() {
    while (true) {
        yield 'red';
        yield 'green'; 
        yield 'yellow';
    }
}

const light = trafficLight();
console.log(light.next().value); // 'red'
console.log(light.next().value); // 'green'

注意事项和限制

限制 描述 解决方案
不能箭头函数 箭头函数不能用作生成器 使用 function* 声明
一次性的 生成器对象遍历一次后耗尽 重新调用生成器函数创建新对象
性能开销 暂停/恢复机制有性能成本 在性能关键代码中谨慎使用
调试复杂性 执行流程不如普通函数直观 使用调试工具和清晰的命名

浏览器兼容性

环境 Generator 支持 备注
现代浏览器 ✅ Chrome 39+, Firefox 26+, Safari 10+ 全面支持
Node.js ✅ Node.js 4.0+ 需要 --harmony flag 或 6.0+ 完全支持
Babel 转译 ✅ 通过 regenerator-runtime 兼容旧环境
TypeScript ✅ 全面支持 编译为 ES5/ES6

Generator 函数为 JavaScript 带来了协程-like 的能力,是实现惰性计算、状态机和复杂控制流的强大工具,同时也是 async/await 的底层基础。


JavaScript 生成器 vs Async/Await

生成器没有被 async/await 取代,它们有各自不同的应用场景。

Async/await 是生成器在异步编程方面的语法糖,但生成器在其他领域仍有不可替代的价值。

特性 生成器 (Generator) Async/Await 关系
主要用途 惰性计算、状态机、数据流 异步操作控制流 不同领域
语法 function* + yield async + await 语法相似但用途不同
返回值 Generator 对象 Promise 完全不同
执行控制 可暂停、可恢复 自动暂停、自动继续 生成器更底层

生成器没有被取代,而是:

  1. 在异步编程领域:Async/Await 提供了更简洁的语法,可以看作是生成器的"升级版"

  2. 在其他领域:生成器在惰性计算、状态机、数据流处理等方面仍有不可替代的价值

  3. 互补关系:它们解决不同的问题,在现代 JavaScript 中共存

选择建议

  • 处理异步操作 → 使用 Async/Await

  • 处理复杂状态、惰性计算、数据流 → 使用生成器

  • 需要精细控制执行流程 → 使用生成器


关联阅读推荐

JavaScript 生成器与迭代器对比(附:Array Iterator 对象详解)

JavaScript Promise 全面总结

JavaScript async/await 全面总结

JavaScript 懒加载全面总结

相关推荐
Mr_WangAndy8 天前
C++_chapter15_C++重要知识点_auto,function,bind,decltype
c++·decltype·bind·function·可调用对象
花伤情犹在1 个月前
Java Stream 高级应用:优雅地扁平化(FlatMap)递归树形结构数据
java·stream·function·flatmap
大龄码农有梦想9 个月前
Spring AI如何调用Function Calling
人工智能·function call·function·spring ai·deepseek·qwen模型
Yongqiang Cheng1 年前
C 语言函数指针 (Pointers to Functions, Function Pointers)
function·c 语言函数指针·pointer
橘色的喵1 年前
基于现代 C++17 的模块化视频质量诊断处理流程设计
c++·com·any·function·视频质量·流程优化
命运之手1 年前
【Coroutines】Implement Python Generator by Kotlin Coroutines
python·kotlin·generator·coroutine
子非鱼9211 年前
【前端】ES6:Promise对象和Generator函数
前端·javascript·es6·promise·generator
小李飞刀李寻欢1 年前
function call学习之2
开发语言·python·大模型·gpt4·function
imred1 年前
C++:std::function的libc++实现
c++·stl·template·function·libc++