js中的內存泄漏

概述

以前雖然知道函數做用域, 上下文, 做用域鏈, 閉包, 引用清除與標記清除等概念, 可是總以爲既然有標記清除, js就不怎麼會發生內存泄漏. 今天查了下資料, 梳理了一下, 記錄下來供之後開發時參考, 相信對其餘人也有用.node

全局變量

function foo(arg) {
bar = "this is a hidden global variable";
}

如上代碼, 聲明瞭一個全局變量, 它不會被自動回收, 因此會形成內存泄漏. 須要手動回收, 改爲以下所示:chrome

方法一(推薦)
function foo(arg) {
var bar = "this is a hidden global variable";
}

方法二
function foo(arg) {
bar = "this is a hidden global variable";
// Do something;
bar = null;
}

計時器

var someResource = getData();
setInterval(function() {
    var node = document.getElementById('Node');
    if(node) {
    // Do stuff with node and someResource.
    node.innerHTML = JSON.stringify(someResource));
    }
}, 1000);

上面的計時器不斷的執行函數, 在執行的時候會調用外面的變量someResource, 因此someResource一直在內存中沒法被釋放. 要修正這種內存泄漏只能設置一個計時器的中止條件了.緩存

var someResource = getData();
setInterval(function() {
    var node = document.getElementById('Node');
    if(node) {
    // Do stuff with node and someResource.
    node.innerHTML = JSON.stringify(someResource));
    }
}, 1000);
if(timesRun === 60){
clearInterval(interval);
}

dom相關操做

<div id="container">  
</div>

$('#container').bind('click', function(){
    console.log('click');
}).remove();

上面刪除了dom可是沒有刪除綁定的事件, 也會形成內存泄漏. 解決方法是先把事件清除再remove.閉包

<div id="container">  
</div>

$('#container').bind('click', function(){
    console.log('click');
}).off('click').remove();

閉包

var leaks = (function(){
    var leak = 'xxxxxx';// 被閉包所引用,不會被回收
    return function(){
        console.log(leak);
    }
})()
leaks();

上面的leak被閉包所引用, 因此不會被回收.解決方法是在執行操做以後釋放掉內存.dom

var leaks = (function(){
    var leak = 'xxxxxx';// 被閉包所引用,不會被回收
    return function(){
        console.log(leak);
        leak = null;
    }
})()
leaks();

不被注意的內存泄漏

有一種內存泄漏很常見, 可是不是那麼明顯, 代碼以下:函數

window.onload=function outerFunction(){
    var obj = document.getElementById("element");
    obj.onclick=function innerFunction(){};
};

這是一個很常見也用的較多的事件綁定代碼, 它其實是閉包引發的內存泄漏問題. 首先咱們在內層函數中聲明瞭一個變量obj, 而後咱們給obj綁定了一個click事件, 這個click事件被外層window引用, 致使innerFunction()函數造成了一個閉包, 雖然這個函數裏面沒有任何表達式, 可是其中的this指向了obj, 因此obj在代碼執行結束以後並不會被清除, 須要手動釋放.修改方法以下:工具

方法一(推薦):
window.onload=function outerFunction(){
    var obj = document.getElementById("element");
    obj.onclick=function innerFunction(){};
    obj = null;
};

方法二(不推薦):
function innerFunction(){};
window.onload=function outerFunction(){
    var obj = document.getElementById("element");
    obj.onclick=innerFunction;
    obj = null;
};

值得注意的是, jQuery封裝瞭解決這種內存泄漏的方法, 它的原理是使用jQuery緩存來綁定事件, 因此存下下面的方法三. 可是爲了保險起見, 仍是建議使用方法一手動清除聲明的變量.this

window.onload=function outerFunction(){
  var obj = document.getElementById("element");
  $(obj).click(function innerFunction(){});
};

查看內存泄漏

使用chrome可以很方便的查看網頁的內存使用狀況, 操做以下:code

  1. 打開開發者工具,選擇 Network 右邊的 Timeline 面板
  2. 在頂部的Capture字段裏面勾選 Memory
  3. 點擊左上角的錄製按鈕。
  4. 在頁面上進行各類操做,模擬用戶的使用狀況。
  5. 一段時間後,點擊對話框的 stop 按鈕,面板上就會顯示這段時間的內存佔用狀況。
相關文章
相關標籤/搜索