內存泄露

來自:http://blog.csdn.net/li2274221/article/details/25217297

想解決內存泄露問題,必須知道什麼是內存泄露,什麼情況下出現內存泄露,才能在遇到問題時,逐個排除。這裏只討論那些不經意間的內存泄露。

一、什麼是內存泄露

內存泄露是指一塊被分配的內存既不能使用,又不能回收,直到瀏覽器進程結束。在C++中,因爲是手動管理內存,內存泄露是經常出現的事情。而現在流行的C#和Java等語言採用了自動垃圾回收方法管理內存,正常使用的情況下幾乎不會發生內存泄露。瀏覽器中也是採用自動垃圾回收方法管理內存,但由於瀏覽器垃圾回收方法有bug,會產生內存泄露。

二、內存泄露的幾種情況

1、當頁面中元素被移除或替換時,若元素綁定的事件仍沒被移除,在IE中不會作出恰當處理,此時要先手工移除事件,不然會存在內存泄露。

複製代碼
<div id="myDiv">
    <input type="button" value="Click me" id="myBtn">
</div>
<script type="text/javascript">
    var btn = document.getElementById("myBtn");
    btn.onclick = function(){
        document.getElementById("myDiv").innerHTML = "Processing...";
    }
</script>
複製代碼

應改成下面

複製代碼
<div id="myDiv">
    <input type="button" value="Click me" id="myBtn">
</div>
<script type="text/javascript">
    var btn = document.getElementById("myBtn");
    btn.onclick = function(){
        btn.onclick = null;
        document.getElementById("myDiv").innerHTML = "Processing...";
    }
</script>
複製代碼

或者採用事件委託

複製代碼
<div id="myDiv">
    <input type="button" value="Click me" id="myBtn">
</div>
<script type="text/javascript">
    document.onclick = function(event){
        event = event || window.event;
        if(event.target.id == "myBtn"){
            document.getElementById("myDiv").innerHTML = "Processing...";
        }
    }
</script>
複製代碼


2、

var a=document.getElementById("xx");
var b=document.getElementById("xxx");
a.r=b;
b.r=a;

 

var a=document.getElementById("xx");
a.r=a;

 

對於純粹的 ECMAScript 對象而言,只要沒有其他對象引用對象 a、b,也就是說它們只是相互之間的引用,那麼仍然會被垃圾收集系統識別並處理。但是,在 Internet Explorer 中,如果循環引用中的任何對象是 DOM 節點或者 ActiveX 對象,垃圾收集系統則不會發現它們之間的循環關係與系統中的其他對象是隔離的並釋放它們。最終它們將被保留在內存中,直到瀏覽器關閉。

 

3、
複製代碼
    
function bindEvent() 
{ 
    var obj=document.createElement("XXX"); 
    obj.onclick=function(){ 
        //Even if it's a empty function 
    } 
}
複製代碼

 

閉包可以維持函數內局部變量,使其得不到釋放。
上例定義事件回調時,由於是函數內定義函數,並且內部函數--事件回調的引用外暴了,形成了閉包
解決之道,將事件處理函數定義在外部,解除閉包
複製代碼
function bindEvent() 
{ 
    var obj=document.createElement("XXX"); 
    obj.onclick=onclickHandler; 
} 
function onclickHandler(){ 
    //do something 
}
複製代碼

 

或者在定義事件處理函數的外部函數中,刪除對dom的引用(題外,《JavaScript權威指南》中介紹過,閉包中,作用域中沒用的屬性可以刪除,以減少內存消耗。)

複製代碼
    
function bindEvent() 
{ 
    var obj=document.createElement("XXX"); 
    obj.onclick=function(){ 
        //Even if it's a empty function 
    } 
    obj=null; 
}
複製代碼

 

4、

a = {p: {x: 1}};
b = a.p;
delete a.p;

 執行這段代碼之後b.x的值依然是1.由於已經刪除的屬性引用依然存在,因此在JavaScript的某些實現中,可能因爲這種不嚴謹的代碼而造成內存泄露。所以在銷燬對象的時候,要遍歷屬性中屬性,依次刪除。

5. 自動類型裝箱轉換

看網上資料,說下面的代碼在ie系列中會導致內存泄露,先提個神,具體泄露與否先不管

var s=”lalala”;

alert(s.length);

 

s本身是一個string而非object,它沒有length屬性,所以當訪問length時,JS引擎會自動創建一個臨時String對象封裝s,而這個對象一定會泄露。這個bug匪夷所思,所幸解決起來相當容易,記得所有值類型做.運算之前先顯式轉換一下:

var s="lalala";

alert(new String(s).length);

 6、某些DOM操作

 IE系列的特有問題 簡單的來說就是在向不在DOM樹上的DOM元素appendChild;IE7中,貌似爲了改善內存泄露,IE7採用了極端的解決方案:離開頁面時回收所有DOM樹上的元素,其它一概不管。

 

本文首發: http://www.cnblogs.com/sprying/archive/2013/05/31/3109517.html

以上知識點來源於《JavaScript高級程序設計》和《JavaScript權威指南》和 http://www.cn-cuckoo.com/2007/08/01/understand-javascript-closures-72.html#clSto

http://www.uml.org.cn/site/201205294.asp

《JavaScript高級程序設計》有關內存部分http://bbs.phpchina.com/thread-221214-1-1.html

待收錄 http://www.feeldesignstudio.com/2013/09/javascript-memory-management


發佈了45 篇原創文章 · 獲贊 24 · 訪問量 10萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章