JavaScript 进阶营让前端飞Web前端之路

javascript垃圾回收与内存泄漏

2018-02-02  本文已影响127人  Husbin

垃圾回收机制

自动垃圾收集机制

局部变量的生命周期

javascript中的2中垃圾回收机制

标记清除(Mark-and-sweep)

引用计数(reference counting)

内存泄漏

javascript中3种常见的内存泄漏

1. 意外的全局变量

举个例子(普通变量):

function fun(){
  globalVar = "this is a hidden global variable";
}
//在函数体内部定义变量,如果没有使用var声明,则定义的变量是全局变量,即成为window的一个属性
//而window总是存在,因此不会被回收

再举个例子(由this创建的变量):

function foo() {
    this.variable = "potential accidental global";
    console.log(this)
}
// Foo 调用自己,this 指向了全局对象(window)
// 而不是 undefined
foo();
image.png

2.被遗忘的计数器或者回调函数

举个例子:

var someResource = getData();
setInterval(function() {
    var node = document.getElementById('Node');
    if(node) {
        // 处理 node 和 someResource
        node.innerHTML = JSON.stringify(someResource));
    }
}, 1000);
//重复计数器并没有使用 clearInterval()终止,导致内存无法回收

3. 脱离DOM的引用

var elements = {
    button: document.getElementById('button'),
    image: document.getElementById('image'),
    text: document.getElementById('text')
};
function doStuff() {
    image.src = 'http://some.url/image';
    button.click();
    console.log(text.innerHTML);
    // 更多逻辑
}
function removeButton() {
    // 按钮是 body 的后代元素
    document.body.removeChild(document.getElementById('button'));
    // 此时,仍旧存在一个全局的 #button 的引用
    // elements 字典所引用的button 元素仍旧在内存中,不能被 GC 回收。
}

4.闭包(正常情况下不会造成内存泄漏)

由于IE9 之前的版本对JScript 对象和COM 对象使用不同的垃圾收集。因此闭包在IE 的这些版本中会导致一些特殊的问题。具体来说,如果闭包的作用域链中保存着一个HTML 元素,那么就意味着该元素将无法被销毁

reference -- javascript高级程序设计第三版

举个例子:

function closure(){
    var element = document.getElementById("someElement");
    element.onclick = function(){
        alert(element.id);
    };
}

解决方案:把element.id 的一个副本保存在一个变量中,从而消除闭包中该变量的循环引用同时将element变量设为null。

function closure(){
    var element = document.getElementById("someElement");
    var id = element.id;
    element.onclick = function(){
        alert(id);
    };
    element = null;
}

reference -- GC的三大基础算法

reference -- javascript内存泄露及其避免

闭包会造成内存泄漏吗?

上一篇下一篇

猜你喜欢

热点阅读