花都网站建设公司天蝎信息给别人做网站被诉侵权

张小明 2026/3/12 14:53:58
花都网站建设公司天蝎信息,给别人做网站被诉侵权,wordpress禁用媒体库,网站过期了怎么办JavaScript学习笔记#xff1a;17.闭包 上一篇用模块搞定了代码的“部门分工”#xff0c;这一篇咱们来攻克JS中“既神秘又核心”的概念——闭包#xff08;Closures#xff09;。你可能听过“闭包能保留变量”“闭包会导致内存泄漏”#xff0c;但始终没搞懂它到底是什么…JavaScript学习笔记17.闭包上一篇用模块搞定了代码的“部门分工”这一篇咱们来攻克JS中“既神秘又核心”的概念——闭包Closures。你可能听过“闭包能保留变量”“闭包会导致内存泄漏”但始终没搞懂它到底是什么也可能在写防抖节流、私有变量时无意中用过它却不知道背后的原理。其实闭包一点都不玄乎它就像函数的“带钥匙管家”外部函数相当于“主人”执行完后作用域本应“关门大吉”但内部函数“管家”偷偷揣着“钥匙”引用外部函数的变量即使主人走了管家还能随时打开门访问里面的“财物”变量。今天咱们就用“房间与钥匙”的生活化比喻把闭包的形成原理、实战用法、优缺点和避坑指南彻底讲透让你从“模糊感知”到“熟练运用”。一、先破案为什么需要闭包普通函数的痛点普通函数执行完后其作用域会被垃圾回收机制销毁里面的变量也会随之消失就像主人出门后房间被清空再回来啥都没了。但开发中经常需要“保留函数执行后的状态”比如计数器多次调用函数累加同一个变量不是每次都从0开始私有变量不想让外部直接访问的变量只能通过特定方法操作防抖节流需要记住上一次执行的时间判断是否触发下一次。这些场景普通函数搞不定而闭包能完美解决——它能让函数执行后作用域不被销毁变量被“偷偷保留”下来。看个直观例子普通函数vs闭包函数// 普通函数执行后变量消失无法累加functionnormalCounter(){letcount0;count;returncount;}console.log(normalCounter());// 1console.log(normalCounter());// 1count每次都重新初始化无法累加// 闭包函数执行后变量被保留实现累加functionclosureCounter(){letcount0;// 外部函数变量// 内部函数引用外部函数的countreturnfunction(){count;returncount;};}constcounterclosureCounter();// 外部函数执行返回内部函数管家带钥匙出门console.log(counter());// 1管家开门count1console.log(counter());// 2管家再开门count2console.log(counter());// 3变量被持续保留核心差异普通函数的变量随作用域销毁闭包的变量被内部函数引用作用域不销毁变量持续可用。二、闭包的核心原理什么是闭包怎么形成的1. 闭包的定义MDN官方闭包是指一个函数以及其捆绑的周边环境状态lexical environment词法环境的引用的组合。简单说闭包让内部函数可以访问外部函数的作用域即使外部函数已经执行完毕。用“房间比喻”翻译外部函数 主人的房间外部函数变量 房间里的财物内部函数 带钥匙的管家闭包 管家钥匙房间的组合即使主人走了管家还能开门取财物。2. 闭包的形成条件缺一不可闭包不是“写个嵌套函数就是闭包”必须满足三个条件函数嵌套存在内部函数和外部函数嵌套关系变量引用内部函数引用了外部函数的变量/参数管家拿了钥匙外部暴露外部函数执行后内部函数被外部引用管家出门了没被留在房间里。// 满足三个条件闭包形成functionouter(){constouterVar我是外部变量;// 外部函数变量functioninner(){console.log(outerVar);// 内部函数引用外部变量条件2}returninner;// 外部暴露内部函数条件3}constinnerFuncouter();// 外部函数执行内部函数被外部引用innerFunc();// 打印我是外部变量闭包生效// 不满足条件3无闭包内部函数没被外部引用functionouter2(){constouterVar我是外部变量;functioninner2(){console.log(outerVar);}inner2();// 内部函数在外部函数内执行没被外部引用}outer2();// 执行后outer2作用域销毁无闭包3. 闭包的执行过程为什么变量能保留咱们拆解closureCounter的执行过程看懂闭包的“魔法”调用closureCounter()外部函数执行创建外部函数作用域声明count0外部函数返回内部函数此时内部函数引用了count外部函数执行完毕但因为内部函数还引用着它的变量作用域不会被垃圾回收房间没被清空。调用counter()内部函数执行内部函数执行时先在自己的作用域找count找不到顺着作用域链找到外部函数的作用域因为闭包保留了引用访问并修改count实现累加。多次调用counter()重复步骤2count持续被保留和修改。简单说闭包的本质是“作用域链的延长”——内部函数的作用域链永远保留着对外部函数作用域的引用即使外部函数执行完。三、闭包的实战场景这些功能离不开闭包闭包不是“炫技工具”而是很多核心功能的底层实现以下三个场景几乎是前端开发的“必备技能”。1. 场景1实现私有变量隐藏内部状态JS没有原生的私有变量ES6的#私有字段是后来加的闭包是传统实现“私有变量”的唯一方式——让变量只能通过特定方法访问不能被外部直接修改保证数据安全。// 用闭包实现“安全的银行账户”私有变量余额functioncreateBankAccount(initialBalance){// 私有变量外部无法直接访问letbalanceinitialBalance;// 暴露对外接口闭包函数return{deposit(amount){// 存款只能通过这个方法修改余额if(amount0){balanceamount;return存款成功余额${balance};}return存款金额无效;},withdraw(amount){// 取款只能通过这个方法修改余额if(amount0amountbalance){balance-amount;return取款成功余额${balance};}return取款金额无效;},getBalance(){// 查询余额只能通过这个方法访问余额return当前余额${balance};}};}// 使用账户constaccountcreateBankAccount(1000);console.log(account.getBalance());// 当前余额1000console.log(account.deposit(500));// 存款成功余额1500console.log(account.withdraw(300));// 取款成功余额1200// 外部无法直接访问私有变量console.log(account.balance);// undefined无法直接访问account.balance100000;// 无效修改的是对象的新属性不是闭包中的balanceconsole.log(account.getBalance());// 当前余额1200余额未变2. 场景2防抖与节流前端性能优化神器防抖debounce和节流throttle是解决“高频事件触发”如滚动、输入、点击的核心方案它们的底层都依赖闭包保留“上次执行时间”“计时器ID”等状态。1防抖触发后延迟n秒执行期间再次触发则重新计时// 防抖函数闭包实现functiondebounce(fn,delay){lettimerId;// 闭包保留计时器IDreturnfunction(...args){// 再次触发时清除之前的计时器clearTimeout(timerId);// 重新设置计时器延迟执行timerIdsetTimeout((){fn.apply(this,args);// 执行原函数},delay);};}// 用法输入框搜索避免输入时频繁请求接口constsearchInputdocument.querySelector(input);functionsearch(keyword){console.log(搜索${keyword});// 实际开发中这里是接口请求}// 给搜索函数加防抖延迟500msconstdebouncedSearchdebounce(search,500);searchInput.addEventListener(input,(e){debouncedSearch(e.target.value);});闭包在这里的作用保留timerId让每次触发时都能访问到上一次的计时器实现“清除旧计时器、设置新计时器”。2节流n秒内只执行一次避免频繁触发// 节流函数闭包实现functionthrottle(fn,interval){letlastTime0;// 闭包保留上次执行时间returnfunction(...args){constcurrentTimeDate.now();// 距离上次执行时间超过interval才执行if(currentTime-lastTimeinterval){fn.apply(this,args);lastTimecurrentTime;// 更新上次执行时间}};}// 用法滚动事件避免滚动时频繁触发functionhandleScroll(){console.log(滚动触发);// 实际开发中这里是滚动加载、位置计算等}// 给滚动函数加节流1秒内只执行一次constthrottledScrollthrottle(handleScroll,1000);window.addEventListener(scroll,throttledScroll);3. 场景3函数工厂批量生成带状态的函数用闭包批量生成具有相同逻辑但不同状态的函数比如批量生成“带固定前缀的日志函数”“带特定权限的接口请求函数”。// 函数工厂生成带固定前缀的日志函数functioncreateLogger(prefix){// 闭包保留前缀returnfunction(message){consttimenewDate().toLocaleTimeString();console.log([${prefix}][${time}]${message});};}// 批量生成不同类型的日志函数constinfoLoggercreateLogger(INFO);consterrorLoggercreateLogger(ERROR);constwarnLoggercreateLogger(WARN);// 使用infoLogger(用户登录成功);// [INFO][14:30:00] 用户登录成功errorLogger(接口请求失败);// [ERROR][14:30:05] 接口请求失败warnLogger(参数格式错误);// [WARN][14:30:10] 参数格式错误每个日志函数都保留着自己的prefix逻辑相同但状态独立这就是闭包的“状态隔离”能力。四、闭包的优缺点一把“双刃剑”闭包很强大但不是万能的它是一把“双刃剑”有优点也有需要警惕的缺点。1. 优点保留状态函数执行后保留变量实现累加、缓存等功能数据私有隐藏内部变量只暴露指定接口保证数据安全逻辑复用批量生成带状态的函数减少重复代码。2. 缺点重点避坑内存泄漏风险闭包引用的外部函数变量不会被垃圾回收若长期不释放会占用额外内存严重时导致内存泄漏调试困难闭包延长了作用域链变量的生命周期变得复杂调试时难以追踪变量的修改路径。五、避坑指南正确使用闭包避免踩雷1. 避坑1避免不必要的闭包及时释放引用不需要保留状态时不要用闭包闭包不用时手动解除引用让垃圾回收机制回收变量// 反面例子长期持有闭包不释放constcounterclosureCounter();// ... 不再使用counter但没有解除引用// 闭包中的count会一直存在占用内存// 正面例子不用时解除引用letcounterclosureCounter();counter();// 使用counternull;// 解除引用闭包中的变量会被垃圾回收2. 避坑2循环中的闭包陷阱经典面试题这是闭包最经典的坑用var声明循环变量闭包会引用同一个变量导致所有内部函数执行时拿到的都是最后一个值。// 反面例子循环中的闭包陷阱constarr[];for(vari0;i3;i){arr.push(function(){console.log(i);// 内部函数引用循环变量ivar声明全局作用域});}// 执行数组中的函数arr[0]();// 3arr[1]();// 3arr[2]();// 3所有函数拿到的都是i的最终值3原因var声明的i是全局变量循环中所有内部函数引用的都是同一个i循环结束后i3所以执行时都打印3。解决方案用let声明循环变量let有块级作用域每次循环都会创建新的i用立即执行函数IIFE创建独立作用域。// 解决方案1用let声明推荐constarr[];for(leti0;i3;i){arr.push(function(){console.log(i);// 每个函数引用的是当前循环的i块级作用域});}arr[0]();// 0arr[1]();// 1arr[2]();// 2// 解决方案2用IIFE兼容旧环境constarr[];for(vari0;i3;i){(function(j){arr.push(function(){console.log(j);// 每个函数引用的是IIFE的参数j独立作用域});})(i);// 立即执行传入当前i的值}arr[0]();// 0arr[1]();// 1arr[2]();// 23. 避坑3闭包不要引用过大的变量闭包会保留外部函数的整个作用域而不是只保留引用的变量。如果外部函数有很多大变量比如大数组、大对象即使内部函数只引用了一个小变量整个作用域的变量都会被保留导致内存浪费。// 反面例子闭包引用外部函数的大变量functionouter(){constbigDatanewArray(1000000).fill(0);// 大数组占用大量内存constsmallVar我只需要这个;returnfunction(){console.log(smallVar);// 只引用了smallVar但bigData也会被保留};}// 正面例子只保留需要的变量避免引用大变量functionouter(){constsmallVar我只需要这个;// 大变量放在不需要的地方或手动释放constbigDatanewArray(1000000).fill(0);bigDatanull;// 手动释放大变量returnfunction(){console.log(smallVar);};}六、总结闭包的核心价值与本质闭包的本质是“作用域链的延长与保留”核心价值是“让函数突破作用域的限制保留执行状态”。它不是JS的“特殊功能”而是作用域和作用域链的自然产物——只要满足“嵌套函数、引用外部变量、外部暴露内部函数”三个条件闭包就会自动形成。记住三个核心点闭包是“带钥匙的管家”保留外部函数的变量即使外部函数执行完闭包的核心用法私有变量、防抖节流、函数工厂闭包的使用原则按需使用及时释放避免引用过大变量和循环陷阱。闭包是JS的“进阶门槛”掌握它不仅能写出更优雅、更安全的代码还能理解很多前端框架和工具的底层实现比如React的hooks、Vue的响应式。下一篇笔记咱们会聊JS的“异步进阶”——Async/Await解锁更简洁的异步编程方式。
版权声明:本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!

投资手机网站源码网上卖东西哪个平台好

想要为你的应用添加实时消息推送功能?yudao-cloud WebSocket模块提供了完整的解决方案,让新手也能轻松构建高性能实时通信系统。无论你是需要系统通知、在线客服还是团队协作,这里都有简单易懂的配置方法。 【免费下载链接】yudao-cloud ruoy…

张小明 2026/3/10 16:00:36 网站建设

如何让网站打不开 解析wordpress加载中

企业如何降低AI成本?选择Qwen3-32B的理由 在AI应用快速渗透各行各业的今天,越来越多企业面临一个现实难题:既要追求大模型带来的智能跃升,又不得不面对高昂的使用成本与数据安全风险。调用闭源API按token计费,动辄每月…

张小明 2026/3/10 16:00:37 网站建设

网站设计网络推广优化怎么做网站官方电话

影刀RPA一键提取Zozone评论数据,效率提升1500%!🚀 还在手动复制粘贴商品评论?每天重复翻页、截图、整理数据,耗时耗力还容易漏?今天带你用影刀RPA实现评论数据智能提取,万条评论5分钟搞定&#…

张小明 2026/3/10 16:00:43 网站建设

江苏太仓建设局网站捷克网站后缀

第一章:Open-AutoGLM轻量化裁剪技术全景解析Open-AutoGLM作为新一代开源大语言模型,其在边缘设备部署场景下面临着计算资源受限的挑战。为实现高效推理与低延迟响应,轻量化裁剪技术成为核心突破口。该技术通过结构化剪枝、知识蒸馏与量化感知…

张小明 2026/3/10 16:00:49 网站建设

适合用于网站开发的工具wordpress相册汉化版

题目描述 51. N 皇后 - 力扣(LeetCode) 按照国际象棋的规则,皇后可以攻击与之处在同一行或同一列或同一斜线上的棋子。 n 皇后问题 研究的是如何将 n 个皇后放置在 nn 的棋盘上,并且使皇后彼此之间不能相互攻击。 给你一个整数…

张小明 2026/3/10 16:06:47 网站建设

做外贸需掌握的网站阿克苏网站建设服务

想和好朋友一起长期开荒《我的世界》,经常出现“房主电脑出问题全员掉线;只有房主在才能游玩,房主不能玩时其他人不能玩该存档;”等问题,能否有一个方法,能解决这些问题呢?有的,兄弟,有的&#…

张小明 2026/3/10 16:06:54 网站建设