对于闭包的理解及其容易内存泄漏的原因
闭包这个知识点在javaScript中算是一个较难的点,之前看过很多关于闭包的文章,只知道闭包是在函数中创建函数,具体用来干嘛以及经常提到的闭包容易造成内存泄漏都不是很了解
废话不多说首先看下闭包的作用
作用:由于作用域链的存在,位于作用域链顶层可以轻易获取到位于作用域链底层的变量,而作用域链底层无法获取到作用域链顶层的变量,闭包就是用于解决这个问题所产生的
上代码
下方代码为一个典型的闭包,通过使用闭包在在外部获取到了函数作用域内部的变量,在person函数中定义了一个变量mike,然后返回一个匿名函数,使用name接受匿名函数,然后调用匿名函数,并在控制台输出1111
function person(){
let mike = 1111
return function(){
return mike
}
}
let name = person() // 使用name接受匿名函数
console.log(name()) // 调用匿名函数输出1111
注:经常有人把匿名函数与闭包弄混,匿名函数与闭包区别是闭包中引用了其他作用域链上的变量
上述为闭包的使用,接下来我们说一下为什么使用闭包容易造成内存泄漏
为什么使用闭包容易造成内存泄漏
首先我们说一下什么是内存泄漏,内存泄漏指的是某些本应该本回收的对象由于某些原因无法被回收导致内存一直被占用无法释放。大量内存泄漏会导致主机内存大量被占用
为什么使用闭包容易造成内存泄漏呢?这里要说一个作用域链的和js垃圾回收机制,JS使用垃圾回收机制的原理是标记清除,比如当一个变量所属的函数作用域被销毁了,变量所存在的作用域没有了,这时JS会给这个变量打上一个标记,待下次垃圾回收时会将其清除。
而在上方的案例中,闭包中引用了person作用域的mike变量,并且person返回的函数赋给了全局作用域中的name变量,这导致了原本应该被回收的mike变量一直被引用无法回收,这样会导致内存泄漏
function person(){
let mike = 1111
return function(){
return mike
}
}
let name = person() // 使用name接受匿名函数
console.log(name()) // 调用匿名函数输出1111
name = null
我们可以通过name=null解除对函数的引用,这样下次垃圾回收时未被引用的mike就能正常被回收了