js引起記憶體洩露的幾種情況分析
記憶體洩露是指一塊被分配的記憶體既不能使用,又不能回收,直到瀏覽器程式結束。
在C++中,因為是手動管理記憶體,記憶體洩露是經常出現的事情。
而現在流行的C#和Java等語言採用了自動垃圾回收方法管理記憶體,正常使用的情況下幾乎不會發生記憶體洩露。
瀏覽器中也是採用自動垃圾回收方法管理記憶體,但由於瀏覽器垃圾回收方法有bug,會產生記憶體洩露。
記憶體洩露引起方式一:
當頁面中元素被移除或替換時,若元素繫結的事件仍沒被移除,在低版本IE中不會作出恰當處理,此時要先手工移除事件,不然會存在記憶體洩露,看如下程式碼:
[HTML] 純文字檢視 複製程式碼<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 = "螞蟻部落"; } </script>
以上程式碼修改如下:
[HTML] 純文字檢視 複製程式碼<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 = "螞蟻部落"; } </script>
或者採用事件委託:
[JavaScript] 純文字檢視 複製程式碼<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 = "螞蟻部落"; } }
記憶體洩露方式二:
[JavaScript] 純文字檢視 複製程式碼var a=document.getElementById("#xx"); var b=document.getElementById("#xxx"); a.r=b; b.r=a;
對於純粹的ECMAScript物件而言,只要沒有其他物件引用物件 a、b,也就是說它們只是相互之間的引用,那麼仍然會被垃圾收集系統識別並處理。但是在低版本的 Internet Explorer 中,如果迴圈引用中的任何物件是 DOM 節點或者 ActiveX 物件,垃圾收集系統則不會發現它們之間的迴圈關係與系統中的其他物件是隔離的並釋放它們。最終它們將被保留在記憶體中,直到瀏覽器關閉。
記憶體洩露方式三:
[JavaScript] 純文字檢視 複製程式碼var elem = document.getElementById('test'); elem.addEventListener('click', function() { alert('You clicked ' + elem.tagName); });
這段程式碼把一個匿名函式註冊為一個DOM結點的click事件處理函式,函式內引用了一個DOM物件elem,就形成了閉包。
這就會產生一個迴圈引用,即:DOM->閉包->DOM->閉包...DOM物件在閉包釋放之前不會被釋放;
而閉包作為DOM物件的事件處理函式存在,所以在DOM物件釋放前閉包不會釋放,即使DOM物件在DOM tree中刪除,由於這個迴圈引用的存在,DOM物件和閉包都不會被釋放。可以用下面的方法可以避免這種記憶體洩露 :
[JavaScript] 純文字檢視 複製程式碼var elem = document.getElementById('test'); elem.addEventListener('click', function() { alert('You clicked ' + this.tagName); // 不再直接引用elem變數 });
記憶體洩露方式四:
[JavaScript] 純文字檢視 複製程式碼function bindEvent() { var obj=document.createElement("XXX"); obj.onclick=function(){ //Even if it's a empty function } }
閉包非常容易構成迴圈引用。如果一個構成閉包的函式物件被指定給,比如一個 DOM 節點的事件處理器,而對該節點的引用又被指定給函式物件作用域中的一個活動(或可變)物件,那麼就存在一個迴圈引用。 [
DOM_Node.onevent -<function_object.[[scope]] -<scope_chain -<Activation_object.nodeRef -<DOM_Node。
形成這樣一個迴圈引用是輕而易舉的,而且稍微瀏覽一下包含類似迴圈引用程式碼的網站(通常會出現在網站的每個頁面中),就會消耗大量(甚至全部)系統記憶體。 解決之道,將事件處理函式定義在外部,解除閉包 :
[JavaScript] 純文字檢視 複製程式碼function bindEvent(){ var obj=document.createElement("XXX"); obj.onclick=onclickHandler; } function onclickHandler(){ //do something }
或者在定義事件處理函式的外部函式中,刪除對dom的引用(題外,《JavaScript權威指南》中介紹過,閉包中,作用域中沒用的屬性可以刪除,以減少記憶體消耗。)
[JavaScript] 純文字檢視 複製程式碼function bindEvent(){ var obj=document.createElement("XXX"); obj.onclick=function(){ //Even if it's a empty function } obj=null; }
記憶體洩露方式五:
[JavaScript] 純文字檢視 複製程式碼a = {p: {x: 1}}; b = a.p; delete a.p;
執行這段程式碼之後b.x的值依然是1.由於已經刪除的屬性引用依然存在,因此在JavaScript的某些實現中,可能因為這種不嚴謹的程式碼而造成記憶體洩露。所以在銷燬物件的時候,要遍歷屬性中屬性,依次刪除。
記憶體洩露方式六:
自動型別裝箱轉換在低版本ie系列中會導致記憶體洩露。
[JavaScript] 純文字檢視 複製程式碼var str="antzone"; console.log(str.length);
str本身是一個string而非object,它沒有length屬性,所以當訪問length時,JS引擎會自動建立一個臨時String物件封裝str,而這個物件一定會洩露。這個bug匪夷所思,所幸解決起來相當容易,記得所有值型別做.運算之前先顯式轉換一下:
[JavaScript] 純文字檢視 複製程式碼var str="antzone"; console.log(new String(str.length);
相關文章
- 記憶體洩露引起的問題記憶體洩露
- [摘譯]js記憶體洩漏常見的四種情況JS記憶體
- js記憶體洩露JS記憶體洩露
- Android中Handler引起的記憶體洩露Android記憶體洩露
- Android 中 Handler 引起的記憶體洩露Android記憶體洩露
- 內部Handler類引起記憶體洩露記憶體洩露
- js記憶體洩露的原因JS記憶體洩露
- Lowmemorykiller記憶體洩露分析記憶體洩露
- [翻譯]查詢Windows記憶體洩露的幾種方法Windows記憶體洩露
- 轉載 ]查詢Windows記憶體洩露的幾種方法Windows記憶體洩露
- 使用 mtrace 分析 “記憶體洩露”記憶體洩露
- 記憶體洩露記憶體洩露
- 異常、堆記憶體溢位、OOM的幾種情況記憶體溢位OOM
- Java字串的substring真的會引起記憶體洩露麼?Java字串記憶體洩露
- [譯]記憶體洩露的八種花樣記憶體洩露
- WebView引起的記憶體洩漏WebView記憶體
- nodejs爬蟲記憶體洩露排查NodeJS爬蟲記憶體洩露
- Js記憶體洩露問題總結JS記憶體洩露
- JavaScript記憶體洩露JavaScript記憶體洩露
- 記憶體洩露嗎記憶體洩露
- 一種不易察覺的記憶體洩露 (轉)記憶體洩露
- Linux記憶體洩露案例分析和記憶體管理分享Linux記憶體洩露
- 如何除錯 Node.js的記憶體洩露除錯Node.js記憶體洩露
- 檢視 Node.js 中的記憶體洩露Node.js記憶體洩露
- Java記憶體洩露的原因Java記憶體洩露
- JAVA 記憶體洩露的理解Java記憶體洩露
- IE中的記憶體洩露記憶體洩露
- Android記憶體洩露分析以及工具的使用Android記憶體洩露
- 記憶體溢位和記憶體洩露記憶體溢位記憶體洩露
- 小題大做 | Handler記憶體洩露全面分析記憶體洩露
- 一個 Vue 頁面的記憶體洩露分析Vue記憶體洩露
- 一個Vue頁面的記憶體洩露分析Vue記憶體洩露
- Spring Boot heapdump洩露記憶體分析方法Spring Boot記憶體
- Android記憶體優化——記憶體洩露檢測分析方法Android優化記憶體洩露
- JavaScript 中 4 種常見的記憶體洩露陷阱JavaScript記憶體洩露
- JavaScript 記憶體洩露的4種方式及如何避免JavaScript記憶體洩露
- 用瀏覽器測試幾種閉包占用記憶體的情況瀏覽器記憶體
- 經驗之談:記憶體洩露的原因以及分析記憶體洩露