当前位置: 首页 > backend >正文

JavaScript中 说说你对闭包的理解?闭包使用场景?

第一步:想象一个时光机

假设你有一个「时光机函数」,它能创造一个小盒子:

function 时光机() {const 秘密 = "2023年的记忆"; // 外部变量(时光胶囊里的内容)function 小盒子() {         // 内部函数(时光胶囊)console.log(秘密);      // 访问外部变量}return 小盒子; // 把胶囊抛向未来
}const 未来胶囊 = 时光机(); // 执行时光机,现在时光机函数已经结束运行了
未来胶囊(); // 输出:"2023年的记忆" (即使时光机消失了,胶囊里的记忆还在!)
关键点
  • 时光机函数:创建时就决定了胶囊里的内容(外部变量)。
  • 小盒子函数:像时空胶囊,把当时的记忆(变量)保存下来。
  • 未来调用:即使外部函数(时光机)早已消失,内部函数(胶囊)依然能记住当时的变量。

闭包的本质:两件套

  1. 外层函数:提供「要被记住的变量」。
  2. 内层函数:像胶水一样粘住这些变量,不让它们被销毁。

闭包使用场景:3 个经典案例

场景1:计数器(保存状态)
function 创建计数器() {let 计数 = 0; // 这个变量会被闭包记住return function() {计数++;console.log(计数);};
}const 计数器A = 创建计数器();
计数器A(); // 1 (每次调用都记住最新的计数)
计数器A(); // 2 const 计数器B = 创建计数器();
计数器B(); // 1 (B的计数是独立的)
  • 类比:每个计数器都是独立的「魔法沙漏」,自己记录时间。

场景2:私有变量(数据隐藏)
function 创建银行账户(初始金额) {let 余额 = 初始金额; // 外部无法直接访问return {存钱: (金额) => 余额 += 金额,查余额: () => `当前余额:${余额}`};
}const 我的账户 = 创建银行账户(100);
我的账户.存钱(50);
console.log(我的账户.查余额()); // "当前余额:150元"
console.log(我的账户.余额); // undefined (无法直接访问)
  • 类比:银行金库(闭包)保护你的钱,只允许通过指定方式操作。

场景3:循环中的陷阱与修复

问题代码

for (var i = 1; i <= 3; i++) {setTimeout(() => console.log(i), 1000); 
}
// 输出:4,4,4 (不是预期的1,2,3)

原因:所有 setTimeout 共享同一个 i(最终值4)。

闭包解法

for (var i = 1; i <= 3; i++) {(function(当前值) { // 用闭包捕获每次循环的i值setTimeout(() => console.log(当前值), 1000);})(i);
}
// 输出:1,2,3
  • 类比:给每次循环拍张快照,保存当时的数值。

闭包注意事项:内存问题

  • 风险:如果闭包长期持有大对象(如 DOM 元素),可能导致内存无法释放。
  • 解决:不再需要时手动解除引用:
    let 工具 = 创建大型工具();
    工具.使用();
    工具 = null; // 告诉浏览器可以回收内存了
    

终极总结

  • 闭包是什么:函数 + 它出生时的环境变量。
  • 核心作用:保存状态、隐藏数据、创建独立空间。
  • 一句话记忆:闭包让函数变成「带着记忆的魔法胶囊」✨
http://www.xdnf.cn/news/3011.html

相关文章:

  • Java练习8
  • GBDT算法原理及Python实现
  • 2024jxcpc D.Magic LCM (logn筛质因子)
  • 百度CarLife实现手机车机无缝互联
  • BT134-ASEMI机器人功率器件专用BT134
  • 告别碎片化!两大先进分块技术如何提升RAG的语义连贯性?
  • 【系统参数合法性校验】spring-boot-starter-validation
  • PowerBI更新后出现提示,无法正常使用,解决办法
  • JavaScript == 和 ===区别,分别在什么情况使用?
  • 角度(degrees)和弧度(radians)转换关系
  • Oracle OCP证书有效期是三年?
  • 5 个开源 MCP 服务器
  • 【MongoDB篇】MongoDB的集合操作!
  • 【angular19】入门基础教程(四):默认的css隔离作用域
  • 基于Java,SpringBoot,HTML水文水质监测预警系统设计
  • 【最新 MCP 战神手册 08】工具使用详解:实现 AI 行动
  • 动态图表 -- eg1
  • Femap许可分配和监控
  • 4月29日星期二今日早报简报微语报早读
  • 优化PCB Via Stub系列(1):一次学会利用层叠设计降低Via Stub损耗
  • 使用 Ziegler-Nichols 法进行 PID 参数整定:实践指南
  • [计算机网络]物理层
  • 力扣-数据结构-二叉树
  • 3D可视化编辑器模版
  • AimRT 从零到一:官方示例精讲 —— 四、logger示例.md
  • 信创产业贡献︱悬镜安全深度参编《2024网信自主创新调研报告》
  • 监控易一体化运维:解锁业务系统管理,助力企业运维升级
  • SOLIDWORKS广东东莞地区代理商哪个服务好?都有哪些代理商?
  • docker 部署前、后端分离项目详细步骤(从打包到部署)
  • 嵌入式学习笔记 - 关于STM32 SPI控制器读取以及写入时,标志位TXE, RXNE的变化