閉包(Closure)的細節(三):閉包與記憶體洩漏

閉包(Closure)的細節(三),閉包與記憶體洩漏:

所謂的記憶體洩漏指的是一些無法被釋放掉的記憶體。而這裡要討論的是早期IE的記憶體洩漏問題。雖然稱之為早期,但不得不承認早期IE的餘毒威力猶存,很多人依然在使用早期的IE,因此還是有了解的必要。

早期的IE很容易造成記憶體洩漏的情形,原因是因為IE對於DOM物件有自己的處理模式。當Javascript物件與DOM物件循環參考時,就會造成記憶體洩漏的問題。因為IE無法回收這樣的記憶體。下面是來自MDN的例子:

function leakMemory() {
    var el = document.getElementById('el');
    var o = { 'el': el };
    el.o = o;
}

物件o的el屬性參考了el物件,而el物件的o屬性參考了o物件。很明顯el物件是個DOM物件,而Javascript物件與DOM物件的循環參考造成了IE瀏覽器無法回收這些記憶體,因此形成了記憶體洩漏的問題。這程式碼其實很明顯很容易看出循環參考的問題,但是如果循環參考隱藏在閉包之中則很不容易發現:


function addHandler() {
    var el = document.getElementById('el');
    el.onclick = function() {
        this.style.backgroundColor = 'red';
    }
    //el=null;
}

看起來完全沒有循環參考的問題,但實際上呢?el物件的屬性參考到了一個函式,很不幸的是這函式其實擁有存取el物件的能力。因此循環參考就此形成。要破壞這種記憶體洩漏其實不難,上例程式碼中的el=null就足以達成這目的,當然也可以在一開始就不使用el變數:

function addHandler(){
    document.getElementById('el').onclick = function(){
        this.style.backgroundColor = 'red';
    }
}

另外的方法就是使用額外的閉包:

function addHandler() {
    var clickHandler = function() {
        this.style.backgroundColor = 'red';
    };
    (function() {
        var el = document.getElementById('el');
        el.onclick = clickHandler;
    })();
}

記憶體洩漏的問題通常不大,除非你大量的洩漏記憶體。不過不管如何,當瀏覽器被關閉時,這類的記憶體洩漏都會被釋放掉。

其他:

如果你想更了解其他閉包觀念,可以參考看看下面這篇文章:閉包(Closure)的基本概念

我把許多閉包的觀念與用法都收集在這篇文章內。

 
 

  按個讚!~支持本站!~

FB推薦載入中