闭包为什么会造成内存泄漏?

Posted 小小码农,可笑可笑

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了闭包为什么会造成内存泄漏?相关的知识,希望对你有一定的参考价值。

先说内存泄漏是什么

内存泄漏:内存泄漏(Memory Leak)是指程序中已动态分配的堆内存由于某种原因程序未释放或无法释放,造成系统内存的浪费,导致程序运行速度减慢甚至系统崩溃等严重后果。

再说说闭包是什么

闭包:引用了另一个函数作用域中变量的函数,一般是嵌套形式。比如:

function closure(){
    let name = '小码农';
    return function(){
        return name;
    }
}

这就是个简单的闭包。

要想理解闭包必须理解函数作用域的创建和使用。

先了解执行上下文和作用域:

https://blog.csdn.net/liuhan4890/article/details/117037516?spm=1001.2014.3001.5501

然后我们再来看闭包,先加一句调用代码

function closure(){
    let name = '小码农';
    return function(){
        return name;
    }
}
let nameFunction = closure();
let result = nameFunction();

代码主要分三步:

1.声明closure方法

2.声明变量nameFunction为closure()的返回值

调用closure上下文,创建作用域链,先创建本身上下文的活动对象0,接着向上寻找创建全局上下文的变量对象1

3.声明变量result为闭包匿名函数的返回值

调用闭包函数的上下文,创建作用域链,先创建本身上下文的活动对象0,接着向上寻找创建closure上下文的活动对象1,最后寻找到全局,创建全局上下文的变量对象2

思考个问题:我们都知道,当某个作用域上下文执行完,若没有其他对象引用其内活动对象,其活动对象将被销毁。

那么当我们执行完closure()函数后,它的活动对象被销毁了嘛?

显然是没有的,因为我们的nameFunction变量返回了闭包匿名函数,而闭包匿名函数中引用了closure上下文活动对象中的name,如果闭包匿名函数不被销毁,则closure的活动对象就不会被销毁,不过closure的作用域链会被销毁,因为其执行完毕了,对应的作用域链也就销毁了。

整体流程如图:

所以我们要想避免内存泄漏,不必须的情况下不要使用闭包,闭包比其他函数更占用内存。若不得不用,要销毁其返回函数,解除对不能释放的活动对象的引用,类似这样

function closure(){
    let name = '小码农';
    return function(){
        return name;
    }
}
let nameFunction = closure();
let result = nameFunction();
nameFunction = null;

 

以上是关于闭包为什么会造成内存泄漏?的主要内容,如果未能解决你的问题,请参考以下文章

闭包为什么会造成内存泄漏?

闭包会造成内存泄漏吗

闭包会造成内存泄漏吗?

闭包会造成内存泄漏吗?

闭包会造成内存泄漏吗?

前端开发中javascript闭包会引发内存泄漏么?