一、什么是闭包
概念:一个函数对周围状态的引用捆绑在一起,内层函数中访问到外层函数的作用域
简单理解:闭包=内层函数+引用的外层函数变量
简单的闭包示例:
为了对变量进行保护,通常会再使用一个函数包裹住闭包结构(上例的outer)
二、闭包作用
- 封闭性(数据私有化):外界无法访问闭包内的数据,如果闭包内声明变量,外界是无法直接访问的。
- 持久性:一般的函数调用完毕后,系统自动注销函数,而闭包在外部函数被调用后,闭包内的数据依然存在,从而实现对数据的持久使用。
优点:
- 可以私有化变量,将变量私有化到函数内部,并在私有化的基础上进行数据保持,减少全局变量;
- 闭包在防抖节流、函数柯里化,都应用到数据保持这个特性
缺点:
- 容易造成内存泄漏,因为闭包创建的变量会一直存在内存中,需要即使置空,否则会造成内存泄漏,影响程序性能(垃圾回收机制)
三、闭包的2个注意点
1、闭包不一定有return:
外部变量想要使用闭包的变量,则此时需要return
2、闭包会存在内存泄漏:
上面这个例子 count变量会存在内存泄漏。
借助垃圾回收机制的标记清除法可以看出:
- result是一个全局变量,代码执行完毕不会立即销毁;
- result使用fn函数
- fn用到fun函数
- fun函数里面用到count
- count被引用就不会被回收,所以一直存在
所以此时,闭包引起了内存泄漏
注意:不是所有的内存泄露都要手动回收的,比如react里面很多闭包不能回收
四.闭包常见的应用场景
举例:在防抖函数中,第一次点击的时候,我们会let一个定时器timer,如果不采用闭包的话,下次触发函数会重新创建一个新的定时器,两个定时器的引用不同,是没有关联的,使用闭包可以直接在内存中找到之前创建的计时器,调用就可以直接拿到对应的定时器的时间
//防抖
function debounce() {
let timer;
//闭包
return function(){
cleaeTimeout(timer);
timer = setTimeout(() = > {
//需要防抖的操作
console.log('防抖成功')
},500);
}
}