Js內存泄露問題總結

最近接受了一個Js職位的面試,問了不少Js的高級特性,才發現長時間使用已知的特性進行開發而忽略了對這門語言按部就班的理解,包括Java我想也是同樣,偶爾在Sun官方看到JDK6.0列舉出來的new features才發現不少東西是本身並不知道或者遺忘了的。看來仍是要堅持總結技術,反覆理解和運用才能保持對任何技術的掌握運用能力阿。

翻了一些Js的新老資料,準備先講講Js的內存泄露問題——
當一個DOM對象包含一個Js對象的引用(例如一個Event Handler), 而這個Js對象又持有對這個DOM對象的引用時,一個環狀引用就行成了。這自己並非什麼錯誤或者Bug,由於Js的回收機制能理解這種環狀的引用結構而且在沒有其餘對象能關聯到環上的時候回收這個環上的全部對象內存。可不幸的是IE瀏覽器中的DOM結構並不受Js解釋機制管理,因此它並不能理解這種失去外界引用的環狀結構,致使環上任何對象都沒法被訪問到,但是內存依舊佔據着,這也就是所謂的Js內存泄露了。

咱們來看一個經典的例子說明問題——程序員

JScript code

(function(limit, delay){
var queue=new Array(10);
var n;
function makeSpan(n){
    var s=document.createElement(‘span’);
    document.body.appendChild(s);
    var t=document.createTextNode(‘ ’+n);
    s.appendChild(t);
    s.onclick=function(e){
    s.style.backgroundColor=’red’;
alert(n);
};
return s;
}

function process(n){
    queue.push(makeSpan(n));
    var s=queue.shift();
    if(s)
        s.parentNode.removeChild(s);
}

function loop()}{
    if(n<limit){
    process(n);
    n+=1;
    setTimeout(loop,delay);
}
}
loop();
})(10000,10);web

 

這個例子的意義是建立出10000個span元素來添加到DOM的body上,而且對其內容填充序號n,緊接着從queue的第一個位置移除建立的span元素,也就是說10000個爲止,不斷的建立再移除,永遠只保留最新建立的那10個。這個例子知足的條件就是DOM元素帶有Js對象即click事件的Event Handler,而Event Handler裏面又帶有這個DOM元素的引用,因而環狀結構行程。

當我在IE上運行這個Js的時候打開任務管理器,很明顯的看到此網頁的內存從55M左右起很穩定的增加直到結束第10000個span建立完畢中止增加時已經到了167M,而在Firefox上運行此Js獲得的數據是從頭至尾內存都不會超過70M。這已經說明IE一直都沒有解決這種Js內存泄露的問題,即便我用的版本已是最新的IE8.0。

能夠想象在現在Ajax運用愈來愈多,用戶體驗要求愈來愈高的狀況下,網頁的體積會愈來愈龐大,可能很頻繁的Js程序員須要作的事情就是在某個DOM元素例如Div裏添加不少Html代碼,用innerHTML賦值進去,而後用戶觸發某事件後又整個替換掉innerHTML,那麼被替換之前的Html代碼極可能帶有這樣的環狀結構,致使頁面只要不刷新,內存就會一直泄露着愈來愈嚴重,直到吃光機器內存。

因此咱們提倡人爲的打破這種環狀結構, 即在DOM元素被拋棄以前移除綁定在上面的Js Event Handler,移除的方法就涉及到DOM事件模型的討論範圍了,我已在另一篇討論文章中詳細機講解W3C標準的DOM事件模型和IE的到底有什麼區別了,有興趣的能夠看一看。

固然瀏覽器廠商特別是IE也但願能負起必定的責任起來,早日大一統,算是爲廣大Js程序員造福吧!
相關文章
相關標籤/搜索