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

内存泄漏会对浏览器造成很大的压力,之前隐隐约约有听说过“如果闭包不处理是一定存内存泄漏的”,这是真的吗?是为什么呢?

函数作用域链

  1. 创建函数outerFun()时,会创建一个预先包含全局变量对象的作用域链,保存在内部的[[Scope]]属性中。

  2. 调用函数outerFun()时,为此函数创建一个执行环境。

  3. 然后复制函数的[[Scope]]属性中的对象构建起执行环境的作用域链。

  4. 此后,创建一个活动对象,推入执行环境作用域链的前端([0]位置)。

此时执行环境的作用域链中包含两个变量对象:全局变量对象(第3步) 、 局部活动对象(第4步)。

函数中访问一个变量时,就会从作用域链中搜索具有相应名字的变量。

函数执行完后,局部活动对象被销毁,内存中仅保存全局作用域。

一、什么是闭包

1、父函数里面嵌套的子函数,子函数访问父函数的局部变量。
2、通过return将子函数暴露到全局作用域,子函数就形成闭包。
3、通过闭包,父函数的局部变量没有被销毁,可通过闭包去调用 ,但同时,这个局部变量也不会被全局变量污染。

二、简单的闭包

function addNum() {
    var num = 0;
    return function () {
        num++
        console.log(num);
    };
}
addNum()();//1

三、关于闭包的内存泄漏

常见闭包

内部函数 被 外部函数 包含时,内部函数 会将 外部函数 的局部活动对象添加到自己的作用域链中。而由于 内部匿名函数 的作用域链 在引用 外部包含函数 的活动对象 ,即使addNum执行完毕了,它的活动对象还是不会被销毁!

即,addNum的执行环境作用域链都销毁了,它的活动对象还在内存中留着呢。

并且根据垃圾回收机制,被另一个作用域引用的变量不会被回收。

所以,除非内部的匿名函数解除对活动变量的引用(解除对匿名函数的引用),才可以释放内存。
*老浏览器(主要是IE6)由于垃圾回收有问题导致很容易出现内存泄漏,现在的主流浏览器已经不会发生这种问题。


// 创建函数 还未调用
var creatFun = addNum()
// 调用函数
var result = creatFun()
// 解除对匿名函数的引用
creatFun = null
循环引用

许多人对闭包和内存泄露的关系有误解,认为闭包一定会引起内存泄漏,其实是不对的,我来谈谈我对他们关系的理解。闭包和内存泄露有关系的地方是,使用闭包的同时比较容易形成循环引用,如果闭包的作用域链中保存着一些DOM节点,这时候就有可能造成内存泄露。这主要是程序员容易引起的bug,不是浏览器的问题。
如果要解决循环引用带来的内存泄露问题,我们只需要把循环引用中的变量设为null即可。将变量设置为null意味着切断变量与它此前引用的值之间的连接。当垃圾收集器下次运行时,就会删除这些值并回收它们占用的内存。

比如:

function  showId() {
    var el = document.getElementById("app")
    el.onclick = function(){
      console.log(el.id) // 这样会导致闭包引用外层的el,当执行完showId后,el无法释放
    }
}

// 改成下面
function  showId() {
    var el = document.getElementById("app")
    var id  = el.id
    el.onclick = function(){
      console.log(id) // 这样会导致闭包引用外层的el,当执行完showId后,el无法释放
    }
    el = null    // 主动释放el
}

参考文档[1]:https://blog.csdn.net/qq_44991493/article/details/116133386

参考文档[2]:https://blog.csdn.net/kk211814/article/details/88323872

  • 6
    点赞
  • 12
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值