JavaScript学习笔记(十七):ES6生成器函数详解

ES6生成器函数详解

ES6引入的生成器函数(Generator Function)是一种特殊的函数,允许通过yield关键字暂停和恢复执行流程。生成器函数在定义时使用function*语法,调用时返回一个生成器对象(Generator Object),而非直接执行函数体。

生成器对象遵循迭代器协议(Iterator Protocol),可通过next()方法逐步执行代码,每次遇到yield时暂停,并返回一个包含valuedone属性的对象。valueyield后的表达式值,done表示生成器是否执行完毕。


语法特性

  1. 定义方式

    使用function*声明生成器函数:

    javascript 复制代码
    function* generatorFunc() {
      yield 1;
      yield 2;
      return 3;
    }
  2. yield关键字
    yield用于暂停函数执行并返回一个值,后续调用next()时从暂停处继续执行。

  3. 迭代器协议

    生成器函数返回的迭代器对象符合迭代器协议,包含next()return()throw()方法。

  4. yield*委托

    用于委托给另一个生成器或可迭代对象:

    javascript 复制代码
    function* generatorA() {
      yield 1;
    }
    function* generatorB() {
      yield* generatorA();
    }

应用场景

  1. 惰性求值生成器适合处理大数据集或无限序列,仅在需要时计算值。例如生成斐波那契数列:

    javascript 复制代码
    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
     
  2. 异步流程控制 生成器可用于简化异步代码,结合yield暂停特性,实现类似同步的异步操作写法。例如:

    javascript 复制代码
    function* fetchUser() {
      const response = yield fetch('https://api.example.com/user');
      const data = yield response.json();
      return data;
    }
    
    const generator = fetchUser();
    const promise = generator.next().value;
    promise.then(response => {
      return generator.next(response).value;
    }).then(data => {
      console.log(generator.next(data).value);
    });
     
  3. 状态机

    生成器天然适合实现状态机逻辑,每个yield代表一个状态节点:

    javascript 复制代码
    function* trafficLight() {
      while (true) {
        yield 'red';
        yield 'yellow';
        yield 'green';
      }
    }
    
    const light = trafficLight();
    light.next().value; // 'red'
    light.next().value; // 'yellow'
     

注意事项

  • 执行顺序 :生成器函数在首次调用next()时才开始执行,而非声明时。
  • 错误处理 :可通过generator.throw()向生成器内部抛出错误,需在函数体内用try/catch捕获。
  • 资源清理 :若提前终止生成器,应调用generator.return()释放资源。
  • 兼容性:旧版浏览器需通过Babel等工具转译。

优化建议

  • 避免频繁创建:对性能敏感场景,复用生成器对象而非重复创建。

  • 结合for...of :遍历生成器时使用for...of语法更简洁:

    javascript 复制代码
    for (const value of fibonacci()) {
      if (value > 100) break;
      console.log(value);
    }
     
  • Promise配合 :使用库如co或异步生成器(ES2018)进一步简化异步代码:

    javascript 复制代码
    async function* asyncGenerator() {
      yield await Promise.resolve(1);
    }
     

总结

生成器函数提供了一种控制执行流程的灵活机制,适用于异步编程、惰性计算和状态管理等场景。尽管现代JavaScript已引入async/await处理异步操作,生成器仍在特定场景下具有独特优势。合理使用生成器能提升代码可读性和维护性,但需注意其执行特性和性能开销。

相关推荐
文艺理科生5 小时前
Nginx 路径映射深度解析:从本地开发到生产交付的底层哲学
前端·后端·架构
千寻girling6 小时前
主管:”人家 Node 框架都用 Nest.js 了 , 你怎么还在用 Express ?“
前端·后端·面试
少控科技6 小时前
QT第6个程序 - 网页内容摘取
开发语言·qt
darkb1rd6 小时前
八、PHP SAPI与运行环境差异
开发语言·网络安全·php·webshell
历程里程碑6 小时前
Linux20 : IO
linux·c语言·开发语言·数据结构·c++·算法
郝学胜-神的一滴6 小时前
深入浅出:使用Linux系统函数构建高性能TCP服务器
linux·服务器·开发语言·网络·c++·tcp/ip·程序人生
承渊政道6 小时前
Linux系统学习【Linux系统的进度条实现、版本控制器git和调试器gdb介绍】
linux·开发语言·笔记·git·学习·gitee
C澒6 小时前
Vue 项目渐进式迁移 React:组件库接入与跨框架协同技术方案
前端·vue.js·react.js·架构·系统架构
lpfasd1236 小时前
两个美国:精英的知识崇拜与底层的反智驯化
笔记
清水迎朝阳6 小时前
解锁读书新体验--有声小说书屋 本地网站的 标注笔记功能
笔记·电子书·读书·标注·有声小说