ES6回顾:闭包->(优点:实现工厂函数、记忆化和异步实现)、(应用场景:Promise的then与catch的回调、async/await、柯里化函数)

news2025/3/17 1:45:01

闭包讲解

ES6回顾:闭包->(优点:实现工厂函数、记忆化和异步实现)、(应用场景:Promise的then与catch的回调、async/await、柯里化函数)

以下是与 JavaScript 闭包相关的常见考点整理,结合 Promise、async/await、缓存结果、工厂函数、柯里化等内容,并依据我搜索到的资料进行详细说明:


1. 闭包(Closure)

  • 定义:由函数及其引用的外部词法环境变量组成,即使外部函数执行完毕,内部函数仍能访问这些变量 。
  • 作用
    • 延长外部函数变量的生命周期,使外部可操作内部数据(如模块化封装)。
    • 避免全局变量污染,实现私有变量 。
  • 缺点:不当使用会导致内存泄漏(变量无法被回收)。
  • 应用场景
    • 缓存结果:通过闭包保存计算结果,避免重复计算(记忆化函数)。
    • 工厂函数:生成带有特定配置的函数实例(如计数器生成器)。
    • 柯里化:拆分多参数函数为链式单参数调用,依赖闭包保存中间参数 。
    • 异步回调:在事件处理或定时器中保留上下文 。

2. Promise

  • 核心概念
    • 三种状态:pendingfulfilledrejected,状态一旦改变不可逆 。
    • 解决回调地狱(Callback Hell),支持链式调用 .then().catch()
  • 常用方法
    • Promise.all():所有 Promise 成功时返回结果数组,任一失败立即拒绝 。
    • Promise.race():首个完成的 Promise 决定最终状态 。
    • Promise.resolve()/Promise.reject():快速创建成功/失败的 Promise 。
  • 手写实现:常考手写 Promise.allPromise.race 的实现 。

3. async/await

  • 本质:基于 Generator 和 Promise 的语法糖,使异步代码更接近同步写法 。
  • 规则
    • async 函数返回 Promise 对象,return 值会被 Promise.resolve() 包装 。
    • await 后接 Promise,暂停当前函数执行直到 Promise 完成(属于微任务)。
    • await 只能在 async 函数内使用,否则需通过立即调用异步函数(如 (async () => { ... })())。
  • 错误处理:用 try...catch 捕获 await 后的 Promise 拒绝 。
  • 执行顺序await 后的代码相当于放入 .then() 中,属于微任务队列 。
function asyncToGenerator(fn) {
    // 返回函数
    return function() {
        const gen = fn.apply(this, arguments);//生成器
        // 方法返回一个Promise对象
        return new Promise((resolve, reject) => {
            function step(key, arg) {
                // console.log(arg)
                let result;
                try {
                    result = gen[key](arg);
                    //生成器返回数据{value,done:bool}
                    // 移除调试日志以保持输出整洁
                } catch (error) {
                    return reject(error);
                }
                //如果执行器执行完成
                if (result.done) {
                    return resolve(result.value);
                }
                //如果执行器未完成,将当前结果传入Promise的resolve方法中,并递归调用step方法
                Promise.resolve(result.value).then(
                    v => step("next", v),
                    e => step("throw", e)
                );
            }
            step("next");
        });
    };
}

// 使用示例(已修复)
const asyncFunction = asyncToGenerator(function* () {
    // 修正 Promise 的创建方式,使用箭头函数包裹 resolve
    const result = yield new Promise(resolve => setTimeout(() => resolve("result"), 1000));
    const result1 = yield new Promise(resolve => setTimeout(() => resolve("result2"), 2000));
    console.log(result, result1); // 输出: "result" "result2"(3秒后)
});

asyncFunction(); // 启动执行

4. 柯里化(Currying)

  • 定义:将多参数函数转换为一系列单参数函数链式调用的技术,依赖闭包保存中间参数 。
  • 示例
  function add(x) {
    return function(y) {
      return x + y;
    };
  }
  add(2)(3); // 5
  • 应用:参数复用、延迟执行、函数组合 。

5. 工厂函数

  • 作用:通过闭包生成具有独立状态的函数实例。例如生成独立的计数器:
  function createCounter() {
    let count = 0;
    return function() {
      return ++count;
    };
  }
  const counter1 = createCounter(); // 独立作用域
  • 场景:封装私有变量、实现模块化 。

6. 闭包与异步编程的结合

  • 事件回调:在闭包中使用 async/await 处理异步逻辑,避免全局变量污染 。
  button.addEventListener('click', () => {
    (async () => {
      const data = await fetchData();
      console.log(data);
    })();
  });
  • 定时器:闭包保存定时器状态,结合 async/await 控制执行流程 。

7. 内存管理

  • 内存泄漏:闭包长期引用外部变量会导致内存无法释放,需及时解除引用(如手动置 null)。
  • 优化:避免不必要的闭包,或在不需要时清除事件监听器、定时器等 。

总结

闭包是 JavaScript 的核心概念,与异步编程(Promise/async/await)、函数式编程(柯里化、工厂函数)紧密相关。理解闭包的作用域机制、内存管理,以及与其他特性的结合方式,是应对面试和实际开发的关键。


async/await 底层实现解析

async/await 是 JavaScript 中处理异步操作的语法糖,其底层实现基于 PromiseGenerator(生成器) 的协同机制。通过分析资料中的代码转换、设计原理和规范定义,其核心实现逻辑可拆解如下:


一、核心依赖:Promise 与 Generator 的协作
  1. Promise 的基础作用
    async/await 的异步控制完全依赖于 Promise 的链式调用。每个 await 表达式本质上会创建一个 Promise,并将后续代码包装到 .then() 中等待执行。例如:

    async function foo() {
      const result = await somePromise; // 等价于 somePromise.then(result => {...})
    }
    

    这种设计使得异步操作的 状态管理错误传播 能够通过 Promise 链式结构实现。

  2. Generator 的流程控制
    Generator 函数通过 yield 关键字暂停执行,并通过迭代器(Iterator)手动恢复。async/await 利用这一特性,将异步代码的 暂停-恢复机制 转化为生成器函数的 yield 操作。例如,以下代码:

    async function a() {
      const res = await asyncTask();
    }
    

    会被 Babel 转换为使用 Generator 的代码:

    function a() {
      return __awaiter(this, void 0, void 0, function* () {
        const res = yield asyncTask();
      });
    }
    

    这里的 yield 替代了 await,而 __awaiter 函数负责管理生成器的迭代。


二、转换逻辑:代码降级与执行器封装

通过 Babel/TypeScript 等工具的代码转换,async/await 的实现可拆解为以下步骤:

  1. 生成器函数包装
    async 函数被转换为生成器函数,await 被替换为 yield。例如:

    // 原始代码
    async function fetchData() {
      const data = await fetch(url);
      return data;
    }
    
    // 转换后代码(简化)
    function fetchData() {
      return __awaiter(this, function* () {
        const data = yield fetch(url);
        return data;
      });
    }
    
  2. 执行器函数(如 __awaiter)的作用
    执行器负责驱动生成器的迭代,并处理 Promise 的链式调用。其核心逻辑如下:

    • 将生成器的每个 yield 值包装为 Promise。
    • 通过 generator.next(value) 将 Promise 的结果传递回生成器。
    • 捕获错误并通过 generator.throw(error) 抛出异常。
    function __awaiter(generator) {
      return new Promise((resolve, reject) => {
        function step(result) {
          if (result.done) {
            resolve(result.value);
          } else {
            Promise.resolve(result.value).then(
              value => step(generator.next(value)), // 传递结果并继续迭代
              error => step(generator.throw(error)) // 抛出错误
            );
          }
        }
        step(generator.next());
      });
    }
    

    此过程实现了 自动迭代错误冒泡,使代码看似同步执行。


三、执行顺序与事件循环的关联
  1. 微任务队列的调度
    await 后的代码会被包装为微任务(Microtask),在 Promise 解决后加入微任务队列。例如:

    async function demo() {
      console.log(1);
      await Promise.resolve();
      console.log(2); // 相当于 Promise.resolve().then(() => console.log(2))
    }
    demo();
    console.log(3);
    // 输出顺序:1 → 3 → 2
    

    这种机制确保了异步代码的执行不会阻塞主线程。

  2. 协程(Coroutine)模型的实现
    async/await 通过生成器和 Promise 模拟了协程的 挂起-恢复 行为:

    • 挂起:在 await 处暂停生成器,释放主线程。
    • 恢复:当 Promise 解决后,通过执行器继续生成器的迭代。

四、错误处理机制的实现
  1. try/catch 的转换
    async 函数中的 try/catch 会被转换为 Promise 的 .catch() 链。例如:

    async function foo() {
      try {
        await somePromise();
      } catch (err) {
        handleError(err);
      }
    }
    

    转换后逻辑:

    function* foo() {
      try {
        const result = yield somePromise();
      } catch (err) {
        handleError(err);
      }
    }
    

    执行器在生成器抛出错误时触发 reject

  2. 未捕获异常的传播
    若未使用 try/catch,错误会通过 Promise 链冒泡到顶层,触发 unhandledrejection 事件。


五、性能与优化考量
  1. 生成器与 Promise 的开销
    async/await 相比原生 Promise 链会引入额外开销(如生成器对象的创建),但在现代引擎中差异可忽略。

  2. 并发的实现方式
    需显式使用 Promise.all() 实现并行,避免顺序等待:

    async function parallel() {
      const [a, b] = await Promise.all([task1(), task2()]); // 并行执行
    }
    

    若直接顺序 await,会导致任务串行执行。


总结:async/await 的架构设计

层级实现机制作用
语法层async/await 关键字提供同步代码风格的异步写法
转换层Babel/TypeScript 代码降级将 async/await 转为 Generator + Promise
运行时层生成器迭代器 + Promise 链管理暂停/恢复、错误传播
事件循环层微任务队列调度确保异步代码非阻塞执行

通过多层抽象,async/await 将复杂的异步流程控制简化为直观的同步式代码,同时保持与 Promise 的完全兼容性。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2316341.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

zend server试用分析

文件:ZendServer-2021.4.1-multi-php-Windows_x86.exe 安装后可以试用30天,想分析下限制原理, 根据安装日志,发现了2个关键的文件: ZendServer\gui\module\Configuration\src\Configuration\License\Wrapper.php ZendServer\gu…

C# NX二次开发:在多个体的模型中如何实现拉伸操作布尔减

大家好,今天接着上一篇拉伸文章去讲。 UF_MODL_create_extruded1 (view source) uf_list_p_tobjectsInputList of objects to be extruded.char *taper_angleInputTaper angle (in degrees).char *limit [ 2 ]InputLimit of extrusion. This is declared as: char …

15 | 定义简洁架构 Store 层的数据类型

提示: 所有体系课见专栏:Go 项目开发极速入门实战课;欢迎加入 云原生 AI 实战 星球,12 高质量体系课、20 高质量实战项目助你在 AI 时代建立技术竞争力(聚焦于 Go、云原生、AI Infra);本节课最终…

2.3 滑动窗口专题:最大连续1的个数 III(LeetCode 1004)

1. ​题目链接 1004. 最大连续1的个数 III - 力扣(LeetCode)https://leetcode.cn/problems/max-consecutive-ones-iii/ 2. ​题目描述 给定一个二进制数组 nums 和一个整数 k,允许将最多 k 个 0 翻转为 1,求翻转后最长的连续 1 …

【微服务】Nacos 配置动态刷新(简易版)(附配置)

文章目录 1、实现方法2、配置依赖 yaml3、验证效果 1、实现方法 环境&#xff1a;Nacos、Java、SpringBoot等 主要是在boostrap.yaml中的data-id属性下配置refresh:true来实现动态更新 2、配置依赖 yaml 具体的版本参考官方的说明&#xff1a;官方版本说明 <!--读取boo…

六十天前端强化训练之第二十天React Router 基础详解

欢迎来到编程星辰海的博客讲解 看完可以给一个免费的三连吗&#xff0c;谢谢大佬&#xff01; 目录 一、核心概念 1.1 核心组件 1.2 路由模式对比 二、核心代码示例 2.1 基础路由配置 2.2 动态路由示例 2.3 嵌套路由实现 2.4 完整示例代码 三、关键功能实现效果 四、…

用 DeepSeek 构建 Vue.js 底层架构:高效协作与问题解决实践

文章目录 1. **DeepSeek 与 Vue.js 的完美协作**2. **问题背景**3. **问题分析与解决**3.1 **动态路由未正确生成**3.2 **路由路径配置错误**3.3 **路由嵌套问题**3.4 **通配符路由未配置** 4. **DeepSeek 的核心价值** 在现代前端开发中&#xff0c;Vue.js 以其简洁的语法和灵…

深入探讨RAID 5的性能与容错能力:实验与分析(磁盘阵列)

前言—— 本实验旨在探讨 RAID 5 的性能和容错能力。通过创建 RAID 5 阵列并进行一系列读写性能测试及故障模拟&#xff0c;我们将观察 RAID 5 在数据冗余和故障恢复方面的表现&#xff0c;以验证其在实际应用中的可靠性和效率。 首先说明&#xff1a;最少三块硬盘, 使用 4 块…

蓝桥杯备赛-二分-技能升级

问题描述 小蓝最近正在玩一款 RPG 游戏。他的角色一共有 NN 个可以加攻击力的技能。 其中第 ii 个技能首次升级可以提升 AiAi​ 点攻击力, 以后每次升级增加的点数 都会减少 Bi。「AiBi⌉Bi​。「Bi​Ai​​⌉ (上取整) 次之后, 再升级该技能将不会改变攻击力。 现在小蓝可以…

电子招采软件系统,如何实现10年可追溯审计

一、在当前经济环境下&#xff0c;中小企业面临着巨大的生存压力&#xff0c;传统产业的数字化转型迫在眉睫。AI技术为企业的低成本高效发展提供了新机会&#xff0c;混合办公成为新常态&#xff0c;数据安全法的深入落实则进一步推动企业重视数据安全。区块链存证技术凭借独特…

Ubuntu从源代码编译安装QT

1. 下载源码 wget https://download.qt.io/official_releases/qt/5.15/5.15.2/single/qt-everywhere-src-5.15.2.tar.xz tar xf qt-everywhere-src-5.15.2.tar.xz cd qt-everywhere-src-5.15.22. 安装依赖库 sudo apt update sudo apt install build-essential libgl1-mesa-d…

X86 RouterOS 7.18 设置笔记七:不使用Upnp的映射方法

X86 j4125 4网口小主机折腾笔记五&#xff1a;PVE安装ROS RouterOS X86 RouterOS 7.18 设置笔记一&#xff1a;基础设置 X86 RouterOS 7.18 设置笔记二&#xff1a;网络基础设置(IPV4) X86 RouterOS 7.18 设置笔记三&#xff1a;防火墙设置(IPV4) X86 RouterOS 7.18 设置笔记四…

数字隔离器,如何提升储能系统的安全与效能?

随着全球对光伏、风电等可再生能源需求的持续增长&#xff0c;在全球能源转型的浪潮中&#xff0c;储能技术凭借着可平衡能源供需、提高能源利用效率等优势&#xff0c;已成为实现 “双碳” 目标的核心支撑。据国家能源局公布数据显示&#xff0c;截至2024年底&#xff0c;我国…

基于UniApp + Vue3开发的智能汉字转拼音工具

基于UniApp Vue3开发的智能汉字转拼音工具 项目简介 这是一个基于 UniApp Vue3 开发的智能汉字转拼音工具&#xff0c;前端使用 Vue3 构建界面&#xff0c;后端采用 Classic ASP 提供接口支持&#xff0c;通过 pinyin-pro 库实现精准的中文转拼音功能。本工具支持以下特性&…

PyTorch 深度学习实战(14):Deep Deterministic Policy Gradient (DDPG) 算法

在上一篇文章中&#xff0c;我们介绍了 Proximal Policy Optimization (PPO) 算法&#xff0c;并使用它解决了 CartPole 问题。本文将深入探讨 Deep Deterministic Policy Gradient (DDPG) 算法&#xff0c;这是一种用于连续动作空间的强化学习算法。我们将使用 PyTorch 实现 D…

Angular由一个bug说起之十四:SCSS @import 警告与解决⽅案

SCSS import 警告与解决⽅案 ⚠ 警告信息 在 SCSS 中&#xff0c;使⽤ import 可能会产⽣以下警告&#xff1a; Deprecation Warning: Sass import rules are deprecated and will be removed in Dart Sass 3.0.0. ? 为什么会有这个警告&#xff1f; Sass 官⽅已经废弃 imp…

PyTorch系列教程:基于LSTM构建情感分析模型

情感分析是一种强大的自然语言处理&#xff08;NLP&#xff09;技术&#xff0c;用于确定文本背后的情绪基调。它常用于理解客户对产品或服务的意见和反馈。本文将介绍如何使用PyTorch和长短期记忆网络&#xff08;LSTMs&#xff09;创建一个情感分析管道&#xff0c;LSTMs在处…

SEO新手基础优化三步法

内容概要 在网站优化的初始阶段&#xff0c;新手常因缺乏系统性认知而陷入技术细节的误区。本文以“三步法”为核心框架&#xff0c;系统梳理从关键词定位到内容布局、再到外链构建的完整优化链路。通过拆解搜索引擎工作原理&#xff0c;重点阐明基础操作中容易被忽视的底层逻…

Tcp网络通信的基本流程梳理

先来一张经典的流程图 接下介绍一下大概流程&#xff0c;各个函数的参数大家自己去了解加深一下印象 服务端流程 1.创建套接字&#xff1a;使用 socket 函数创建一个套接字&#xff0c;这个套接字后续会被用于监听客户端的连接请求。 需要注意的是&#xff0c;服务端一般有俩…

PHP函数缺陷详解

无问社区-官网&#xff1a;http://www.wwlib.cn 本期无人投稿&#xff0c;欢迎大家投稿&#xff0c;投稿可获得无问社区AI大模型的使用红包哦&#xff01; 无问社区&#xff1a;网安文章沉浸式免费看&#xff01; 无问AI大模型不懂的问题随意问&#xff01; 全网网安资源智…