以前雖然知道函數做用域, 上下文, 做用域鏈, 閉包, 引用清除與標記清除等概念, 可是總以爲既然有標記清除, 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); }
<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