首頁 > web前端 > js教程 > 詳談JavaScript記憶體洩漏_javascript技巧

詳談JavaScript記憶體洩漏_javascript技巧

WBOY
發布: 2016-05-16 16:31:28
原創
1121 人瀏覽過

1、什麼是閉包、以及閉包所涉及的作用域鏈這裡就不說了。

2、JavaScript垃圾回收機制

     JavaScript不需要手動地釋放內存,它使用一種自動垃圾回收機制(garbage collection)。當一個物件無用的時候,也就是程式中無變數引用這個物件時,就會從記憶體中釋放掉這個變數。

複製程式碼 程式碼如下:

    var s = [ 1, 2 ,3];
    var s = null;
    //這樣原始的陣列[1 ,2 ,3]就會被釋放掉了。

3、循環引用

     三個物件 A 、B 、C

     AàBàC :A的某一屬性引用著B,同樣C也被B的屬性引用著。如果將A清除,那麼B、C也被釋放。

     AàBàCàB :這裡增加了C的某一屬性引用B對象,如果這是清除A,那麼B、C不會被釋放,因為B和C之間產生了循環引用。

複製程式碼 程式碼如下:

    var a = {};
    a.pro = { a:100 };
    a.pro.pro = { b:100 };
    a = null ;
    //這種情況下,{a:100}和{b:100}就同時也被釋放了。
           
    var obj = {};
    obj.pro = { a : 100 };
    obj.pro.pro = { b : 200 };
    var two = obj.pro.pro;
    obj = null;   
    //這種情況下 {b:200}不會被釋放掉,而{a:100}被釋放了。
 

4、循環引用與閉包

複製程式碼 程式碼如下:

    function outer(){
        var obj = {};
        function inner(){
            //這裡引用了obj物件
        }
        obj.inner = inner;
    }

這是一種及其隱藏的循環引用,。當呼叫一次ou​​ter時,就會在其內部創建obj和inner兩個對象,obj的inner屬性引用了inner;同樣inner也引用了obj,這是因為obj仍然在innerFun的封閉環境中,準確的講這是由於JavaScript特有的「作用域鏈」。
因此,閉包非常容易建立循環引用,幸運的是JavaScript能夠很好的處理這種循環引用。

5、IE中的記憶體洩漏

    IE中的記憶體洩漏有好幾種,這裡有詳細的解釋(http://msdn.microsoft.com/en-us/library/bb250448.aspx)。

    這裡只討論其中一種,即循環引用所造成的記憶體洩漏,因為,這是一種最普遍的情況。

    當在DOM元素或一個ActiveX物件與普通JavaScript物件之間存在循環引用時,IE在釋放這類變數時存在特殊的困難,最好手動切斷循環引用,這個bug在IE 7中已經被修復了(http://www.quirksmode.org/blog/archives/2006/04/ie_7_and_javasc.html)。

   “IE 6 suffered from memory leaks when a circular reference between several objects, among which at least one DOM node, was created. This problem has been solved in IE 7. ”

    如果上面的例子(第4點)中obj引用的不是一個JavaScript Function物件(inner),而是一個ActiveX物件或Dom元素,這樣在IE中所形成的循環引用無法得到釋放。

複製程式碼 程式碼如下:

    function init(){
        var elem = document.getElementByid( 'id' );
        elem.onclick = function(){
            alert('rain-man');
            //這裡引用了elem元素
        };
    }

Elem引用了它的click事件的監聽函數,同樣函數透過其作用域鏈也引用回了elem元素。這樣在IE中即使離開目前頁面也不會釋放這些循環引用。

6、解決方法

   基本的方法就是手動清除這個循環引用,下面一個十分簡單的例子,實際應用時可以自行建立一個addEvent()函數,並且在window的unload事件上對所有事件綁定進行清除。

複製程式碼 程式碼如下:

    function outer(){
        var one = document.getElementById( 'one' );
        one.onclick = function(){};
    }
    window.onunload = function(){
        var one = document.getElementById( 'one' );
        one.onclick = null;
    };

 其它方法(by:Douglas Crockford)

複製程式碼 程式碼如下:

/**
 * 遍歷某一元素節點及其所有後代元素
 *
 * @param Elem node  所要清除的元素節點
 * @param function func  進行處理的函數
 *
 */
function walkTheDOM(node, func) {
    func(node);
    node = node.firstChild;
    while (node) {
        walkTheDOM(node, func);
        node = node.nextSibling;
    }
}
/**
 * 清除dom節點的所有引用,防止記憶體外洩
 *
 * @param Elem node  所要清除的元素節點
 *
 */
function purgeEventHandlers(node) {
    walkTheDOM(node, function (e) {
        for (var n in e) {           
            if (typeof e[n] ===
                    'function') {
                e[n] = null;
            }
        }
    });

以上就是JavaScript記憶體洩漏的相關內容以及解決方案了,有需要的小夥伴可以參考下

相關標籤:
來源:php.cn
本網站聲明
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn
熱門教學
更多>
最新下載
更多>
網站特效
網站源碼
網站素材
前端模板