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

闭包讲解

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 的创建方式,使用箭头函数包裹 resolveconst 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.rhkb.cn/news/34488.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

阿里云服务器购买及环境搭建宝塔部署springboot和vue项目

云服务器ECS_云主机_服务器托管_计算-阿里云 一、前言 对于新手或者学生党来说,有时候就想租一个云服务器来玩玩或者练练手,duck不必花那么多钱去租个服务器。这些云服务厂商对学生和新手还是相当友好的。下面将教你如何快速搭建自己的阿里云服务器&…

ABAP语言的动态编程(4) - 综合案例:管理费用明细表

本篇来实现一个综合案例:管理费用明细表。报表在实际项目中,也有一定的参考意义,一方面展示类似的报表,比如管理费用、研发费用等费用的明细,使用业务比较习惯的展示格式;另一方面正好综合运用前面学习的动…

【Python办公】Excel通用匹配工具(双表互匹)

目录 专栏导读1、背景介绍2、库的安装3、核心代码4、完整代码总结专栏导读 🌸 欢迎来到Python办公自动化专栏—Python处理办公问题,解放您的双手 🏳️‍🌈 博客主页:请点击——> 一晌小贪欢的博客主页求关注 👍 该系列文章专栏:请点击——>Python办公自动化专…

2025-03-15 吴恩达机器学习2——线性回归模型

文章目录 1 概述1.1 案例1.2 分析 2 代价函数2.1 代价函数公式2.2 理解代价函数2.3 可视化代价函数 3 梯度下降3.1 实现步骤3.2 理解梯度下降3.3 学习率 4 最佳实践4.1 导入数据4.2 代码实现4.3 可视化 1 概述 ​ 线性回归模型是使用最广泛的学习算法,让我们从一个…

Webpack 前端性能优化全攻略

文章目录 1. 性能优化全景图1.1 优化维度概览1.2 优化效果指标 2. 构建速度优化2.1 缓存策略2.2 并行处理2.3 减少构建范围 3. 输出质量优化3.1 代码分割3.2 Tree Shaking3.3 压缩优化 4. 运行时性能优化4.1 懒加载4.2 预加载4.3 资源优化 5. 高级优化策略5.1 持久化缓存5.2 模…

实验篇| CentOS 7 下 Keepalived + Nginx 实现双机高可用

为什么要做双机高可用?‌ 想象一下:你的网站突然宕机,用户无法访问,订单流失、口碑暴跌…💸 ‌双机热备‌就是解决这个痛点的终极方案!两台服务器互为备份,724小时无缝切换,保障业务…

C语言【内存函数】详解加模拟实现

目录&#xff1a; 1. memcpy使用和模拟实现 2. memmove使用和模拟实现 3. memset函数的使用 4. memcmp函数的使用 以上函数均包含在一个头文件<string.h>里面 一、memcpy的使用和模拟实现。 memcpy函数介绍&#xff1a; 函数原型&#xff1a; void * memcpy ( void…

Flutter——Android与Flutter混合开发详细教程

目录 1.创建FlutterModule项目&#xff0c;相当于Android项目里面的module库&#xff1b;2.或者编辑aar引用3.创建Android原生项目3.直接运行跑起来 1.创建FlutterModule项目&#xff0c;相当于Android项目里面的module库&#xff1b; 2.或者编辑aar引用 执行 flutter build a…

Windows根据文件名批量在文件夹里查找文件并复制出来,用WPF实现的详细步骤

项目前言 在日常工作和生活中&#xff0c;我们常常会遇到需要从大量文件中根据文件名批量查找特定文件并复制到指定位置的情况。手动一个个查找和复制文件不仅效率低下&#xff0c;还容易出错。使用 Windows Presentation Foundation (WPF) 可以创建一个用户友好的图形界面应用…

matlab 控制系统GUI设计-PID控制超前滞后控制

1、内容简介 matlab164-控制系统GUI设计-PID控制超前滞后控制 可以交流、咨询、答疑 2、内容说明 略 3、仿真分析 略 4、参考论文 略

【大模型基础_毛玉仁】2.4 基于 Encoder-Decoder 架构的大语言模型

更多内容&#xff1a;XiaoJ的知识星球 目录 2.4 基于 Encoder-Decoder 架构的大语言模型2.4.1 Encoder-Decoder 架构2.4.2 T5 语言模型1&#xff09;T5 模型结构2&#xff09;T5 预训练方式3&#xff09;T5 下游任务 2.4.3 BART 语言模型1&#xff09;BART 模型结构2&#xff0…

AI智能代码疫苗技术,赋能数字化应用内生安全自免疫

“DevSecOps市占率持续领先&#xff0c;IAST探针覆盖率十倍增长&#xff0c;代码疫苗技术已成功帮助上千家行业用户成功抵御‘Log4j2.x’等重大未知漏洞的利用攻击。”子芽在腾讯专访中透露。 这是2021年悬镜安全交出的一张成绩单。悬镜安全是DevSecOps敏捷安全先行者&#xf…

【初级篇】如何使用DeepSeek和Dify构建高效的企业级智能客服系统

在当今数字化时代,企业面临着日益增长的客户服务需求。使用Dify创建智能客服不仅能够提升客户体验,还能显著提高企业的运营效率。关于DIfy的安装部署,大家可以参考之前的文章: 【入门级篇】Dify安装+DeepSeek模型配置保姆级教程_mindie dify deepseek-CSDN博客 AI智能客服…

【机器学习-基础知识】统计和贝叶斯推断

1. 概率论基本概念回顾 1. 概率分布 定义: 概率分布(Probability Distribution)指的是随机变量所有可能取值及其对应概率的集合。它描述了一个随机变量可能取的所有值以及每个值被取到的概率。 对于离散型随机变量,使用概率质量函数来描述。对于连续型随机变量,使用概率…

正点原子[第三期]Arm(iMX6U)Linux移植学习笔记-4 uboot目录分析

前言&#xff1a; 本文是根据哔哩哔哩网站上“Arm(iMX6U)Linux系统移植和根文件系统构键篇”视频的学习笔记&#xff0c;在这里会记录下正点原子 I.MX6ULL 开发板的配套视频教程所作的实验和学习笔记内容。本文大量引用了正点原子教学视频和链接中的内容。 引用&#xff1a; …

视频AI方案:数据+算力+算法,人工智能的三大基石

背景分析 随着信息技术的迅猛发展&#xff0c;人工智能&#xff08;AI&#xff09;已经逐渐渗透到我们生活的各个领域&#xff0c;从智能家居到自动驾驶&#xff0c;从医疗诊断到金融风控&#xff0c;AI的应用正在改变着我们的生活方式。而数据、算法和算力&#xff0c;正是构…

MySQL -- 表的约束

概念引入&#xff1a;真正的约束表字段的是数据类型&#xff0c;但是数据类型的约束方式比较单一的&#xff0c;所以需要一些额外的一些约束&#xff0c;用于表示数据的合法性&#xff0c;在只有数据类型一种约束的情况下&#xff0c;我们比较难保证数据是百分百合法。通过添加…

嵌入式Zephyr RTOS面试题及参考答案

目录 Zephyr RTOS 的主要设计目标是什么?适用于哪些领域? Zephyr 支持哪些内核对象类型?举例说明其应用场景。 Zephyr 支持哪些线程同步机制?举例说明其适用场景。 Zephyr 内核支持哪些任务状态?状态转换的条件是什么? Zephyr 如何实现低延迟中断处理?(如直接中断服…

《TCP/IP网络编程》学习笔记 | Chapter 18:多线程服务器端的实现

《TCP/IP网络编程》学习笔记 | Chapter 18&#xff1a;多线程服务器端的实现 《TCP/IP网络编程》学习笔记 | Chapter 18&#xff1a;多线程服务器端的实现线程的概念引入线程的背景线程与进程的区别 线程创建与运行pthread_createpthread_join可在临界区内调用的函数工作&#…

C++相关基础概念之入门讲解(上)

1. 命名空间 C中的命名空间&#xff08;namespace&#xff09;是用来避免命名冲突问题的一种机制。通过将类、函数、变量等封装在命名空间中&#xff0c;可以避免不同部分的代码中出现相同名称的冲突。在C中&#xff0c;可以使用namespace关键字来定义命名空间。 然后我们在调…