📖参考笔记: 90%的面试官都会问的问题!JavaScript知识点-闭包2024年的秋招,张三去了一家互联网公司面试,张三面对面试官 - 掘金
面试官:谈谈对JS闭包的理解及常见应用场景(闭包的作用)使用闭包主要为了设计私有的方法和变量。 缺点是闭包会常驻内存,会 - 掘金
📱含义
含义:当通过调用一个外部函数返回的一个内部函数后,即使外部函数执行已经结束了,但是内部函数引用了外部函数中的变量也依旧需要被保存在内存中,我们把这些变量的集合叫做闭包。
简单理解: 🏖️闭包 = 内层函数 + 外层函数的变量🏖️
☎优点和缺点
优点
- 实现共有变量:在模块化开发中,闭包可以用来创建私有变量并暴露有限的公共接口,实现数据的封装和隔离。
- 做缓存:利用闭包可以存储计算结果,避免重复计算,提高程序效率。
- 封装模块,防止全局变量污染:通过闭包封装变量和函数,可以有效减少全局作用域的污染,保持代码的整洁和可维护性。
缺点
- 闭包会常驻内存,会增大内存使用量,容易造成内存泄漏。退出函数之前,可以将不适用的局部变量全部删除。
- 闭包在父函数外部,容易改变父函数内部变量的值。
闭包导致内存泄漏的解决方法:
-
手动释放闭包的引用:在闭包不再需要访问外部变量时,显式地将闭包或者外部变量设置为
null
。这样可以断开闭包对外部作用域变量的引用,使得垃圾回收机制能够回收这些变量占用的内存。 -
事件处理和定时器清理:确保为所有的事件监听器和定时器设置清除机制,避免它们长时间持有闭包和相关的外部变量。
链接:https://juejin.cn/post/7373675985722556428
📠应用场景
🖱setTimeout传参
原生的setTimeout传递的第一个函数不能带参数,通过闭包可以实现传参效果。
//原生的setTimeout传递的第一个函数不能带参数
setTimeout(function(param){
alert(param)
},1000)
//通过闭包可以实现传参效果
function func(param){
return function(){
alert(param)
}
}
var f1 = func(1);
setTimeout(f1,1000);
💻回调
我们定义行为,然后把它关联到某个用户事件上(点击或者按键)。我们的代码通常会作为一个回调(事件触发时调用的函数)绑定到事件上。
body {
font-size: 12px;
}
<p>字体12px</p>
<p>字体加大2倍</p>
<p>字体加大4倍</p>
<a href="#" id="size-12">12</a>
<a href="#" id="size-14">24</a>
<a href="#" id="size-16">48</a>
function changeSize(size) {
return function () {
document.body.style.fontSize = size + "px";
};
}
var size12 = changeSize(12);
var size14 = changeSize(24);
var size16 = changeSize(48);
document.getElementById("size-12").onclick = size12;
document.getElementById("size-14").onclick = size14;
document.getElementById("size-16").onclick = size16;
🔌封装变量
用闭包定义能访问私有函数和私有变量的公有函数。
//用闭包定义能访问私有函数和私有变量的公有函数。
var counter = (function(){
var privateCounter = 0; //私有变量
function change(val){
privateCounter += val;
}
return {
increment:function(){ //三个闭包共享一个词法环境
change(1);
},
decrement:function(){
change(-1);
},
value:function(){
return privateCounter;
}
};
})();