最新要闻
- 来自38万公里外!我国玉兔二号月球车发新照:这次是“兔子脚印”
- 全球今亮点!野性觉醒!动物园办虎兔交接仪式:兔子差点成“盘中餐”
- 【环球新视野】GXG男士休闲长款羊毛大衣:到手199元
- 天天热头条丨行业唯一!雅迪电动车官宣登上2023年央视春晚
- 世界今亮点!寒气逼人!“裁员潮”席卷美科技巨头:谷歌母公司将裁1.2万人
- 王晶武侠电影 《天龙八部之乔峰传》今日上线“爱优腾”三大平台
- 世界第一高楼迪拜塔点亮中国红:春晚吉祥物“兔圆圆”亮相
- 最低气温跌破-50摄氏度 漠河游客:刚出门就想钻回炕上
- 【速看料】用上自研3.0T发动机 坦克700实车曝光:水泥灰质感十足
- 天天微速讯:做清洁的噩梦!潮汕女子晒大扫除:一家人出动擦镂空家具
- 当前快讯:春节假期7天免通行费!交通部:目前全国高速公路通行畅通
- 大批AMD RX 6000挂掉的原因找到了!挖矿、湿度影响
- 专家:春节期间最好每餐七分饱
- 环球热文:比苹果良心!微信支付春节福利来了:App Store充值9折
- 环球最新:毫米波无线投屏带来全新体验 红魔电竞显示器上手
- 环球今日报丨戴尔发布新款32寸6K显示器:剑指苹果Pro Display XDR
手机
iphone11大小尺寸是多少?苹果iPhone11和iPhone13的区别是什么?
警方通报辅警执法直播中被撞飞:犯罪嫌疑人已投案
- iphone11大小尺寸是多少?苹果iPhone11和iPhone13的区别是什么?
- 警方通报辅警执法直播中被撞飞:犯罪嫌疑人已投案
- 男子被关545天申国赔:获赔18万多 驳回精神抚慰金
- 3天内26名本土感染者,辽宁确诊人数已超安徽
- 广西柳州一男子因纠纷杀害三人后自首
- 洱海坠机4名机组人员被批准为烈士 数千干部群众悼念
家电
JavaScript 作用域和闭包
一、作用域
JavaScript 中的作用域指的是变量和函数的可访问范围。JavaScript 使用词法作用域,即作用域由代码的书写结构决定,而不是运行时环境。
【资料图】
二、闭包
JavaScript 中,闭包是一个函数对象,它可以访问定义该函数的作用域里的变量,即使函数已经返回。闭包的特点是,它可以在其相关环境不存在时保留变量。闭包可以被保存到变量中并在以后使用。它具有两个特征,一是可以访问外部函数的变量,二是它可以在外部函数执行结束后继续执行。闭包可以用来实现私有变量,记忆函数(缓存),高阶函数等功能。
简单来说,闭包是一个能够访问其他函数作用域中变量的函数。
三、闭包的应用
1、封装私有变量
闭包的一个常见用途是构建私有变量。当你使用闭包封装变量时,外部代码就无法访问这些变量了。
下面是一个使用闭包来创建私有变量的示例:
function createCounter() { let count = 0; return function() { return count++; }}let counter = createCounter();console.log(counter()); // 0console.log(counter()); // 1console.log(counter()); // 2
在这个例子中,createCounter
函数返回了一个闭包。这个闭包访问了创建时所在作用域中的变量 count
。外部代码不能访问这个变量,因此这个变量就成为了一个私有变量。
2、高阶函数
高阶函数是指一个函数,其参数或返回值是一个函数。闭包可以用来捕获函数作用域中的变量,并将它们传递给高阶函数。
下面是一个使用闭包来构建高阶函数的示例:
function createMultiplier(x) { return function(y) { return x * y; }}let double = createMultiplier(2);console.log(double(3)); //6console.log(double(5)); //10let triple = createMultiplier(3);console.log(triple(2)); //6console.log(triple(3)); //9
在这个例子中,createMultiplier
是一个高阶函数,它返回了一个闭包。 这个闭包捕获了它定义时所在作用域中的变量 x 并在闭包内部运用这个变量进行运算。
3、延迟计算(高阶函数的一种具体实现)
通过闭包,可以将函数和其词法环境存储在变量中,直到需要执行函数时再调用它。
function makeAdder(x) { return function (y) { return x + y; };}const add5 = makeAdder(5);console.log(add5(3)); // 8
4、实现私有属性和私有方法
闭包还有一个重要的应用场景就是实现面向对象编程中的私有属性和私有方法。
以下是一个使用闭包实现私有属性和私有方法的例子:
function Person(name) { let _name = name; this.getName = function() { return _name; } this.setName = function(name) { _name = name; }}let p = new Person("John");console.log(p.getName()); // Johnp.setName("Mike");console.log(p.getName()); // Mike
在这个例子中,_name 是私有变量,getName() 和 setName() 是私有方法。由于它们是在构造函数中定义的,所以它们可以访问到 _name 变量。而外部无法直接访问 _name 变量。
闭包的使用能够帮助我们实现面向对象编程中的私有属性和私有方法,使代码更加安全和可维护。
5、实现计数器(封装私有变量的一种具体实现)
function makeCounter() { let count = 0; return function() { return count++; };}const counter = makeCounter();console.log(counter()); // 0console.log(counter()); // 1console.log(counter()); // 2
6、实现防抖函数
通过闭包可以实现一个防抖函数,在指定时间内只会执行一次。
function debounce(fn, delay) { let timer = null; return function() { clearTimeout(timer); timer = setTimeout(() => { fn.apply(this, arguments); }, delay); };}const debouncedFn = debounce(() => { console.log("Debounced function called.");}, 1000);
7、实现节流函数
通过闭包可以实现一个节流函数,每隔一段时间执行一次。
function throttle(fn, delay) { let timer = null; return function() { if (!timer) { timer = setTimeout(() => { fn.apply(this, arguments); timer = null; }, delay); } };}const throttledFn = throttle(() => { console.log("Throttled function called.");}, 1000);
8、实现自执行函数
通过闭包可以实现一个自执行函数,可以在定义时立即执行。
(function () { console.log("Self-executing function called.");})();
9、实现单例模式
单例模式是一种常用的设计模式,它保证一个类只有一个实例,并且提供了一个全局访问点来访问这个实例。使用闭包可以很容易地实现单例模式。
下面是一个使用闭包实现单例模式的例子:
const Singleton = (function() { let instance; function createInstance() { return {}; } return { getInstance: function() { if (!instance) { instance = createInstance(); } return instance; } };})();console.log(Singleton.getInstance() === Singleton.getInstance()); // true
在这个例子中,Singleton 函数返回了一个对象,它包含一个 getInstance() 方法。这个方法用于获取单例的实例。如果实例不存在,则调用 createInstance() 创建一个新的实例。因为 createInstance() 和 instance 变量都在闭包中定义,所以只能被 getInstance() 方法访问到。
这样就可以保证单例模式的特性了,在多次调用 getInstance() 方法时,都会返回同一个实例。
10、实现模块模式
通过闭包可以实现模块模式,将代码封装在单独的模块中,保证变量和函数不会污染全局作用域。
const myModule = (function () { let _privateValue = "Hello, World!"; function _privateFunction() { console.log(_privateValue); } return { publicFunction: function () { _privateFunction(); } };})();myModule.publicFunction(); // "Hello, World!"console.log(_privateValue); // ReferenceError: _privateValue is not defined
11、实现类似于块级作用域的效果
通过闭包可以实现类似于块级作用域的效果,将变量和函数封装在一个单独的作用域中,防止变量污染。
for (var i = 0; i < 5; i++) { (function(index) { setTimeout(() => { console.log(index); }, 1000 * i); })(i);}
12、实现缓存(记忆函数)
通过创建一个闭包并将需要缓存的数据存储在其中,可以在需要使用数据时直接从缓存中获取,而不需要重新计算或重新读取。
下面是一个使用闭包实现缓存的例子:
function expensiveFunction() { console.log("Calculating..."); return Math.random();}function cache(fn) { let cache = {}; return function (arg) { if (!cache[arg]) { cache[arg] = fn(arg); } return cache[arg]; };}const cachedFunction = cache(expensiveFunction);console.log(cachedFunction(5)); // Calculating... 0.5console.log(cachedFunction(5)); // 0.5
在这个例子中,我们有一个计算代价高昂的函数 expensiveFunction(),它每次都会计算一个随机数。我们使用 cache() 函数将其包装在闭包中,并将计算结果存储在缓存中。当调用 cachedFunction() 函数时,如果缓存中已经有结果,则直接返回缓存中的结果,而不需要重新计算。如果缓存中没有结果,则调用 expensiveFunction() 计算结果并将其存储在缓存中。
在这个例子中,我们将参数作为缓存的键,这样就可以缓存不同参数的结果。
闭包缓存的好处是:
- 可以避免重复计算或重复读取
- 可以提高程序的性能
- 可以将缓存逻辑与主程序逻辑分离,更加清晰
缺点是:
- 缓存数据会占用内存
- 缓存会在某些时候过期,导致数据不准确
- 如果缓存过大,会导致性能下降
使用闭包实现缓存是一种常用的优化方式,可以有效地提高程序的性能。然而,也需要注意缓存的维护与管理,避免缓存过大或过期导致的数据不准确的问题。
除了使用闭包实现缓存还有其他方法,比如使用Map,WeakMap,localStorage来存储缓存数据。
使用闭包实现缓存的方法是一种常用的优化方式,可以有效地提高程序的性能。通过将缓存逻辑封装在闭包中,可以将缓存逻辑与主程序逻辑分离,使程序更加清晰。
闭包是 JavaScript 中一种强大的特性,理解和掌握它的使用方式可以帮助我们编写出更加高效、可维护的代码。
需要注意的是,闭包会增加函数作用域链的长度,因此如果闭包中存在大量的变量或者被频繁使用,可能会导致内存占用过多,影响性能。
除此之外,闭包也可能会导致作用域链上的变量不能及时被垃圾回收机制回收,这就是所谓的闭包内存泄漏问题。所以,使用闭包时,需要注意内存使用的问题。
在使用闭包时需要注意一些问题,例如:
- 使用完闭包后,应该及时释放不再使用的闭包。
- 避免在循环中使用闭包,这可能会导致不同的闭包引用同一个变量。
- 在使用闭包时,需要谨慎使用 this 和 arguments 变量,因为它们可能会被闭包引用。
同时闭包的应用也会影响到代码的可读性和可维护性,需要在使用时考虑清楚。
如果遇到需要闭包且涉及到回调函数,可以使用箭头函数来简化代码,而箭头函数本身也是闭包的一种,但是其处理方式与普通的函数不同,对作用域和this的绑定等也有区别。
另外,在 ECMAScript6 中,新增了 let 和 const 命令,它们可以用来声明块级作用域的变量。let 和 const 命令能够更好地处理变量提升问题,并且使用块级作用域可以更好地控制变量的生命周期,减少内存泄漏的风险。
在编写代码时,应该根据实际需要来选择使用 var、let 或 const 命令声明变量。使用 var 命令时,应该尽量避免使用全局变量;使用 let 和 const 命令时,应该尽量避免变量提升问题。
总的来说,JavaScript的闭包是一种非常强大的特性,可以帮助我们更好地处理作用域、私有变量、高阶函数等问题。但是,使用闭包也需要注意一些性能和内存使用的问题。
JavaScript 作用域和闭包
来自38万公里外!我国玉兔二号月球车发新照:这次是“兔子脚印”
世界热门:SOFAJRaft模块启动过程
全球今亮点!野性觉醒!动物园办虎兔交接仪式:兔子差点成“盘中餐”
【环球新视野】GXG男士休闲长款羊毛大衣:到手199元
天天热头条丨行业唯一!雅迪电动车官宣登上2023年央视春晚
世界今亮点!寒气逼人!“裁员潮”席卷美科技巨头:谷歌母公司将裁1.2万人
王晶武侠电影 《天龙八部之乔峰传》今日上线“爱优腾”三大平台
世界第一高楼迪拜塔点亮中国红:春晚吉祥物“兔圆圆”亮相
最低气温跌破-50摄氏度 漠河游客:刚出门就想钻回炕上
世界今热点:[数据结构] 队列 (C语言)
Wallpaper Engine壁纸提取工具,pkg文件提取静态图片,pkg文件转jpg,pkg文件转png,pkg文件转图像,pkg文件提取图像
【速看料】用上自研3.0T发动机 坦克700实车曝光:水泥灰质感十足
天天微速讯:做清洁的噩梦!潮汕女子晒大扫除:一家人出动擦镂空家具
天天简讯:LeetCode.面试题02.05-链表求和-题解分析
当前快讯:春节假期7天免通行费!交通部:目前全国高速公路通行畅通
大批AMD RX 6000挂掉的原因找到了!挖矿、湿度影响
专家:春节期间最好每餐七分饱
环球热文:比苹果良心!微信支付春节福利来了:App Store充值9折
环球最新:毫米波无线投屏带来全新体验 红魔电竞显示器上手
C 忽远忽近的距离【2023牛客寒假算法基础集训营3 】
环球今日报丨戴尔发布新款32寸6K显示器:剑指苹果Pro Display XDR
焦点精选!徐志胜首登春晚:担心在春晚嘴瓢每天练绕口令
当前快看:土耳其上空出现碟形透镜云:恍若UFO、相当震撼
年终奖入手iPhone 14:听我的别贴膜 没啥用
一口一只小苍蝇:不恶心吗?
3小时挪动300米堵哭了!去海南自驾请注意:需预约购票
世界关注:读函数式编程思维笔记02_转变思维
【世界新视野】《塞尔达传说:王国之泪》即将发售 网友抱怨任天堂还没开始宣发
当前观点:广东游客专程来感受-50℃的漠河 有车企趁极寒测试车辆性能
每日消息!张朝阳用物理知识解构《流浪地球2》:吴京听惊讶 竖拇指点赞
【世界报资讯】首发4899元!机械革命推出新款蛟龙5游戏本:锐龙7 7735H+RTX 3050
热点聚焦:10余款皮肤齐上架!玩家深夜把《王者荣耀》充值系统挤崩溃了
学习笔记——SpringMVC消息转换器概述;使用消息转换器处理请求报文;使用消息转换器处理响应报文;使用消息转换器处理Json格式数据
今日热讯:D 宿命之间的对决【2023牛客寒假算法基础集训营3】
用AutoHotkey解决B站客户端缓存视频m4s合并成mp4提示解析失败
天天热门:刚提特斯拉Model Y电池遇故障 五天坏两次!车主“愤怒”要求换新车
近十日全国平均气温为历史第三暖:大部分地区天气利于出行
世界讯息:HGAME2023_WP_WEEK2
双向链表
每日短讯:爱做美甲女生注意了!过年美甲小心致癌突变
实时焦点:2023央视春晚没有贾玲张小斐:此前连续5年登台
苹果着手开发iPhone 16 Pro!灵动岛要扩大
《流浪地球2》首波口碑好评如潮 吴京:希望中国电影以该片为底气
关注:Intel扼杀超频!13代酷睿再也不能“白嫖”了
世界球精选!iPhone 14 Pro系列供需已平衡:之前要等一个多月 一机难求
【环球时快讯】了解Spring
刷掌支付快到了:腾讯新刷掌设备专利发布
最新消息:身家千万老板被骗到缅甸做诈骗:3个月暴瘦40多斤
世界快消息!Lisp的求值规则
每日速讯:需求激增!国内客运航班量连续13天上涨
焦点热门:禁止中国玩家参加炉石赛事引众怒 用户抵制卸载无惧:暴雪态度没缓和
【世界速看料】全力推动首车落地!贾跃亭回应FF落地湖北黄冈:何时归国依旧成谜
环球即时:打工一年享受享受怎么了 HKC 27寸4K 144Hz显示器3449元
每日热讯!2023春节档预售票房破5亿:张艺谋电影《满江红》领跑
世界快消息!我的2022年终总结
全球热议:春节宠物寄养生意火爆!猫狗“标间”599元/天 “总统套房”5400元/月
广州明起向外卖骑手、快递员发“春节补贴”:每人每天150元
【焦点热闻】男子开“电动爹”回东北:200公里充次电 充了14次
【全球独家】微软XGP彻底赢麻了 索尼再次面临“断气”风险
国产最强皮卡!长城山海炮6x6版内饰谍照:相当豪华
世界观速讯丨您是否存在想在浏览器动态编译razor的组件的想法?
Obsidian 插件(一):DataView 的使用
天天短讯!单向循环链表
京东代言人!中国选手谷爱凌夺2023年首个冠军
马斯克没钱了?推特拍卖数百件办公资产:“小蓝鸟”雕像10万美元成交
今日关注:灵山“网红牛”不幸被车撞死:一片狼藉
天天快报!无短板办公利器!联想小新Air 14 Plus图赏
短讯!深圳一公司年会送员工保时捷跑车:还有宝马、特斯拉
全球聚焦:单向链表
全球今头条!商务部:每卖4辆新车就有1辆新能源
TGA年度最佳游戏 《双人成行》Steam新史低:73.26元
微资讯!八核酷睿+满血RTX 3060!机械革命极光Pro图赏
春节档电影票均价7年来首降:你会选择看哪部电影过年?
一加11独家适配!国产魂Like手游《帕斯卡契约》新增高品质震动
国人不识货?本田思域TYPE R因太畅销在日本暂停接单
全球速读:今年这回 我们总可以对春节档有点期待了吧
热消息:雷军回顾2022年:小米13得到大家认可最开心
育碧喜加一:《雷曼:疯狂兔子》免费领!兔年玩疯兔
世界热门:大摆锤高处停摆近10分钟 游乐场回应:两边游客体重相近所致
焦点快报!新年第一月iPhone已降价2次!苹果14首降超千元 国内用户喊真香抄底
每日视点!印度8岁女孩放弃4亿家产出家 看透世俗享乐:从没看过电视
世界热消息:学习笔记——springMVC中视图及视图解析器对象;视图控制器
当前快讯:撕破脸!暴雪禁止中国玩家参加炉石赛事引众怒 国内玩家地址卸载所有游戏
获得版号后首测!米哈游《崩坏:星穹铁道》三测定档1月24日
环球观速讯丨英首相车内讲话未系安全带遭批 IIHS曾做测试:后排不系结果可怕!
今日要闻!《三体》电视剧更新8集 豆瓣评分增至8.1 网友担忧:原创角色正让抠书式还原走形
荣耀MagicBook V 14可升级MagicOS 7.0:新增键鼠共享功能
数据结构:树状数组 学习笔记
环球观热点:Downie V4.6.4 for Mac 视频下载工具
进海南遭世纪大堵车 3小时挪300米?当地回应:前段时间轮渡停航
每日快讯!奥迪胜诉!蔚来在德国被禁止使用“ES6”、“ES8”等名称
世界快消息!卖8万能成爆款?比亚迪海鸥内饰谍照曝光:看齐大哥海豚
当前观察:担心的事发生了 滑雪游客乘坐缆车时坠落!官方回应
环球新资讯:谁能阻挡!比亚迪双线再“扩军”:产能新增或超百万辆
本故事纯属虚构是什么意思?本故事纯属虚构的下一句是什么?
尺子的刻度是什么意思?尺子的刻度是从几开始的?
社会发展的根本动力是什么?社会发展的源泉是什么?
肌底是什么意思?肌底液是干什么用的?
交通问题有哪些?交通问题反馈打什么电话?