學習JavaScript以內存泄漏

接上回我寫了一篇關於閉包的博客《學習JavaScript之閉包》, 最後談到閉包致使的問題時留了一個尾:javascript

在IE9如下的瀏覽器中會有內存泄漏的問題。前端

今天的博客就繼續探索一下內存泄漏的問題。java

淺談JavaScript垃圾回收機制

1.標記清除

一開始垃圾收集器會給內存中的全部變量作一個標記,以後當程序運行進入相應的環境時,會去掉環境中的變量和被環境中變量引用的變量標記;當退出該環境後,沒法再被訪問的變量又從新被標記,這些被從新標記的變量就會被垃圾收集器回收。瀏覽器

2.引用計數

記錄每一個值被引用的次數,當被引用次數爲0時該值纔會被回收。若是某個值被其餘對象引用(賦給某個變量),引用次數+1;若是再也不被引用則-1。閉包

閉包致使的內存泄漏怎麼產生的

在IE9之前的瀏覽器中,DOM對象的垃圾回收機制就是使用引用計數(雖然JS引擎是用標記清除),所以一旦產生循環引用(好比下面這個例子)內存就會一直被佔用而沒法回收。函數

function a () {
  var div = document.getElementById('myTitle')
  div.onclick = function () {
    alert(div.id)
  }
}

這段代碼中變量div中保存了一個HTML元素對象,又建立了一個事件處理程序,其中還直接引用了div.id造成了循環引用,並且這個匿名函數只要存在就能利用閉包的特性訪問到div,所以這個HTML元素的引用至少是1。學習

如何解決內存泄漏的問題

首先要解除循環引用:把div.id賦值給一個變量,而後在匿名函數中引用該變量,由於變量只包含值而不存在對div直接引用,因此解除了循環引用。可是,因爲閉包的特性使得其仍保存着a函數的活動對象(等於間接地在引用HTML元素),所以還須要手動解除div對HTML元素的引用。用代碼寫出來就是:code

function a () {  
   var div = document.getElementById('myTitle')  
   var id = div.id // 解除循環引用
   div.onclick = function () {    
     alert(id)  
   }
   div = null // 手動解除閉包對外部函數活動對象的引用
 }

這樣DOM對象的引用就變成了0,也就會被正常地回收了。對象

博客地址:lbj的前端之路事件

原文連接:學習JavaScript以內存泄漏

相關文章
相關標籤/搜索