闭包造成的内存泄露如何解决

什么是闭包?
闭包就是一个函数,能够访问其他函数内部变量的函数

闭包示例代码

function outer() {
     var  a = '变量1'
     var  inner = function () {
            console.info(a)
     }
     return inner    // inner 就是一个闭包函数,因为他能够访问到outer函数的作用域
}
var  inner = outer()   // 获得inner闭包函数
inner()   //"变量1"

当程序执行完var inner = outer(),其实outer的执行环境并没有被销毁,因为他里面的变量a仍然被被inner的函数作用域链所引用,当程序执行完inner(), 这时候,inner和outer的执行环境才会被销毁调;《JavaScript高级编程》书中建议:由于闭包会携带包含它的函数的作用域,因此会比其他函数占用更多内容,过度使用闭包,会导致内存占用过多。

  • 基本类型变量(Number 、Boolean、Undefined、String、Null)的值一般都是存在栈内存中,
  • 引用类型变量(Array、Object、Function)的值存储在堆内存中,栈内存存储对应空间地址

闭包的作用
1.访问其他函数内部变量
2.保护变量不被内存回收机制回收
3.避免全局变量被污染 方便调用上下文的局部变量 加强封装性

闭包的缺点
闭包长期占用内存,内存消耗很大,可能导致内存泄露

如何避免闭包引起的内存泄漏
1,在退出函数之前,将不使用的局部变量全部删除。可以使变量赋值为null;(示例如下)

 这段代码会导致内存泄露
    window.onload = function(){
        var el = document.getElementById("id");
        el.onclick = function(){
            alert(el.id);
        }
    }
    解决方法为
    window.onload = function(){
        var el = document.getElementById("id");
        var id = el.id;                                      //解除循环引用
        el.onclick = function(){
            alert(id); 
        }
        el = null;                                          // 将闭包引用的外部函数中活动对象清除
    }

2,避免变量的循环赋值和引用。 (示例如上)

循环引用引起的内存泄漏,是因为IE 的bug,循环引用无法自动判断,所以通过拷贝值,把内外引用脱钩,这样就可回收。IE9及其以后已修复。(感谢 猫SirSir 的讲解!)

3,利用Jquery释放自身指定的所有事件处理程序。
由于jQuery考虑到了内存泄漏的潜在危害,所以*它会手动释放自己指定的所有事件处理程序 *。只要坚持使用jQuery的事件绑定方法,就可以一定程度上避免这种特定的常见原因导致的内存泄漏。

这段代码会导致内存泄露
$(document).ready(function() {
    var button = document.getElementById('button-1');
    button.onclick = function() {
         console.log('hello');
         return false;
    };
});
当指定单击事件处理程序时,就创建了一个在其封闭的环境中包含button变量的闭包。
而且,现在的button也包含一个指向闭包(onclick属性自身)的引用。
这样,就导致了在IE中即使离开当前页面也不会释放这个循环。 用jQuery化解引用循环 $(document).ready(
function() { var $button = $('#button-1'); $button.click(function(event) { event.preventDefault(); console.log('hello'); }); });

 

posted @ 2020-10-26 20:59  尖子  阅读(3571)  评论(0编辑  收藏  举报