js闭包一定引发内存泄漏吗

什么是内存泄漏

像c,c++这种语言,有个free函数,用来释放动态分配的内存.若是某个或某些动态分配的变量没有了做用,而且占用的内存很大,足以影响整个程序的运行.这就叫内存泄漏.同理,像js,java这种语言,由v8和jvm等来帮助管理这部份内存.他们管理的时候都不会释放你有可能用到的内存.
如下以js为例.v8并不知道你须要用到哪些对象.因此他只能经过一些条件来判断出你绝对不会使用的对象.好比若是一个对象已经没有了引用,那你确定就没法用js来操做这个对象了,v8就认为这个对象占用的内存是能够释放的了.但他并不必定会当即释放,gc(释放垃圾内存)是有性能损耗的.全部v8的gc也是有必定算法的.假设你有这样一段代码:
let arr = new Array(1000000)
即便你下面不会使用到arr,v8也绝对不会释放掉arr占用的内存,由于还有arr这个引用.怎么来证实这一点呢.前面说过v8的gc时机是有必定的算法的.不过node有一个global.gc()方法,可以全局gc,可是须要--expose-gc参数来执行node进程.node还有一个方法,process.memoryUsage()可以查看这个node进程的内存占用状况.java

输入图片说明

代码1中演示了这两个方法的使用.能够看出第一次强制全局gc,并无将这个1000000长度空数组占用的内存释放掉.内存从最开始的5M上升到了12M.将这个数组的引用去掉后,再次gc,便能释放这部份内存.
那么问题来了,假设我写了段代码,并无将arr置为null,而且之后也不会使用这个arr.那个人代码算是内存泄漏了吗?多是吧,那个人arr所引用的数组长度不是1000000了,而是0.arr=[].那我这还算是内存泄漏吗?我以为不是.感受内存泄漏是个辩证的见解吧,若是某个不会使用的对象,咱们在代码里把他写成了不能让v8释放,这就构成了内存泄漏,我以为谁都写过内存泄漏的代码.要是有一个对象不用了,我就要将他的全部引用置为空.那我还要v8的垃圾回收作什么,我置位空,v8也不见得回收他,倒不如用c语言的free好了.
因此我以为只有没必要要的大内存,因为代码问题,形成v8不能回收.影响了程序的性能,这才叫内存泄漏.而本文要讨论的实际是: js闭包,一定会引发部份内存不能释放吗?node

什么是js闭包

学过js的人应该都了解,js的变量做用域.外部做用域,不能访问内部做用域的变量.反过来能够.而闭包,引用朴灵大大的话,即是在js中,实现外部做用域访问内部做用域中变量的方法叫作闭包.
输入图片说明 在代码2中,内部引用inLead并不能在外部直接访问,可是getInLeadFn做用域里能够访问,包括返回的匿名函数.将这个匿名函数经过执行getInLeadFn引用到外部做用域,即可以间接访问inLead.c++

js闭包会引发内存不能释放吗?

记得刚面试的时候,就有面试官问过我,闭包的危害.当时本身没有回答上来,面试官当时告诉我,会引发内存泄漏.当时本身对内存的概念不太关注.就这样记住了,到后来,愈来愈怀疑这句话.百度,网上也有的言论是这样说的.仍是实践出真知.
输入图片说明 写完整个闭包,能够看出,内存从5M到了14M,gc也还剩13M.可是只要将outLeadFn置位null,即将内部做用域的函数引用去掉,再gc,便能释放内存.
有没有看到,这和代码1是相似的.因此我以为js闭包,只不过是把内部做用域的对象延伸到了外部罢了,就像外部做用域的对象有引用内存不能gc,经过js闭包获得的内部对象若是有引用,也不能gc.
有人会说,inLead这个引用还在指向这个数组呢.引用的内存分配在栈上,对象的内存分配在堆上.当函数执行完以后,函数栈上的内存即可以释放了.当fn这个函数执行完以后,fn里的inLead便被销毁了,不须要等待gc.这也是为何在外层做用域不能再找到inLead了.面试

总结

**js闭包,不会引起内存不能释放,更不会引发内存泄漏.只不过是把内部做用域的对象延伸到了外部罢了,想要经过gc释放这个对象的内存,只须要将引用去掉便可. **有问题,但愿指出,谢谢!算法

相关文章
相关标签/搜索