javascript 闭包的理解、运用和销毁
javascript 闭包的理解、运用和销毁
javascript 闭包的理解和运用
- 什么是闭包?
- 闭包的理解
- 闭包的运用
- 闭包的销毁
什么是闭包?
1、闭包让你可以在一个内层函数中访问到其外层函数的作用域。引用于:MDN-闭包
2、闭包是一种保护私有变量的机制,在函数执行时形成私有的作用域,保护里面的私有变量不受外界干扰。直观的说就是形成一个不销毁的栈环境。引用于:菜鸟教程-JavaScript 闭包
PS:看看就好,看不懂也没关系
闭包的理解
比较直白的来理解闭包概念:
- 形成闭包的条件:
- 内外2层函数
- 内部函数中使用了父函数的变量
- 内部的私有变量外界可以引用,但无法改变,且不轻易被销毁
下面来看代码:
// 外层函数const outerFn = () => {// 私有变量,可以通过内层函数访问,但无法被外界干预let count = 0;// 内层函数const innerFn = () => {console.log('内部count', count++); // 使用了父函数的变量return count;}return innerFn;}const closure = outerFn(); // 这就是一个闭包console.log('返回的count', closure());console.log('返回的count', closure());// 输出结果:// 内部count 0// 返回的count 1// 内部count 1// 返回的count 2
根据结果看出:
- 可通过
closure()
来获取count
的值- 执行多次
closure()
时,count
的值并不会被重置为0
,而是持续叠加,证明outerFn
内的私有变量count
并不会随着执行closure()
后被销毁。
闭包的运用
根据私有变量保护机制、且不易销毁的特性,可运用于缓存机制
// A.JS
window.caCheDataBox = ()=>{let cache = {}; // 缓存数据let cacheKeys = []; // 数据映射的key值const maxCacheCount = 20; // 为了防止内存溢出,规定最大缓存数据数量return {/** 缓存数据* key {string} 映射数据的值* data {any} 需要缓存的数据*/setCache:(key, data)=>{// 判断key值是否已存在if(key in cache){cache[key] = data;}else{cacheKeys.push(key);// 判断已缓存的数据数量是否大于规定最大数量if(cacheKeys.length > maxCacheCount){const delKey = cacheKeys.shift(); // 删除第一个key,保持先进先出delete cache[delKey]; // 删除对应的缓存数据}cache[key] = data;}},/** 获取映射缓存数据* key {string} 根据key值,获取映射的数据* @return 缓存数据 | null*/getCache:(key)=>{if(key in cache){return cache[key];}return null;},/** 清除映射缓存数据* key {string} 根据key值,清除映射的数据* @return 被清除的数据*/clearCache:(clearKey)=>{if(clearKey in cache){const keyIndex = cacheKeys.findIndex(val=>val===clearKey); // 获取key值的下标cacheKeys.splice(keyIndex, 1); // 清除数组中的clearKeyconst clearData = cache[clearKey]; // 保留被清除的数据,用于returndelete cache[clearKey]; // 清除对应的缓存数据return clearData;}return null;},/** 获取全部缓存数据*/getAllCache:()=>{return cache;},/** 清除全部缓存数据,并返回全部缓存数据*/clearAllCache:()=>{const caCheData = cache; cache = {};cacheKeys = [];return caCheData;}};
}(); // 立即执行匿名函数
封装好后,一般使用方法:
// B.JS
// 缓存登陆信息
const ajaxUser = new Promise((resove)=>{// 模拟接口请求setTimeout(()=>{resove({name:'李子玅',url:'=1011.2124.3001.5343'});}, 3000);
});// 初始化数据
ajaxUser.then((data)=>{caCheDataBox.setCache('userInfo',data); // 缓存用户数据
});
// C.JS
// 获取缓存的用户信息
const userInfo = caCheDataBox.getCache('userInfo');
console.log('userInfo',userInfo);
// 输出结果:
// userInfo {name:'李子玅',url:'=1011.2124.3001.5343'}
// D.JS
// 用户登出,清除用户信息
caCheDataBox.clearCache('userInfo');
其他例子我就不写了,基本都涵盖在上面的例子中了。用法和原理都是差不多的。
具体可参考:MDN-闭包
闭包的销毁
const outerFn = () => {let count = 0;const innerFn = () => {console.log('count', ++count);}return innerFn;}let closure = outerFn(); // 创建第一个闭包closure();closure();closure = outerFn(); // 销毁第一个闭包,创建第二个闭包closure();closure();closure = null; // 销毁闭包// 输出结果:// count 1// count 2// count 1// count 2
由上面的例子可以看出来,当第二次为
closure
赋值后,再次执行2次closure()
时,count
的结果并不会变成3,4
,而是又变回了1,2
。
这表示着,当第二次赋值的时候,第一个闭包就会被垃圾回收销毁掉,而第三次赋值为null
时,则是把第二次的闭包也销毁了。
简单的总结:
- 关于闭包的销毁
- 可在模块或应用结束后来进行空赋值处理,进行销毁,比如上面的:
closure = null
- 等待页面被关闭,才会被销毁。
- 至于为什么会要这么处理才会被销毁呢?具体的话可以网上找一下 javascript 回收机制,有兴趣的童鞋可以去了解了解。
最新文章
- ROS1云课→29如何借助导航实现走迷宫机器人
- matlab stats里的f值,MATLAB 回归分析regress,nlinfit,stepwise函数
- 林达华博士对数学的见解
- LruCache源码浅析
- JMeter BeanShell 应用
- ABAP 设置ALV复选框
- ext3文件系统基础
- 关于ADFS的局限性,你了解多少?
- 机器学习几种距离比较:欧拉距离(Euclidean Distance)、曼哈顿距离(Manhattan Distance)和明可夫斯基距离(Minkowski Distance)
- HashTable详解、源码、扩容、深入理解HashTable、HashTable多线程并发问题
- extern的几种用法
- 【区块链
- 人力资源的名词解释
- Jmeter脚本两种录制方式
- python爬虫(网页解析)
- shiro反序列化漏洞学习(工具+原理+复现)
- Qt数据库(三)利用QSqlQuery类执行SQL语句(一)