由閉包引出的垃圾回收

由閉包引出的垃圾回收

閉包的特性

  1. 函數嵌套函數
  2. 函數內部能夠引用外部的參數和變量
  3. 參數和變量不會被垃圾回收機制回收

閉包的定義

閉包 是指有權訪問另外一個函數做用域中的變量的函數,建立閉包最多見的方式就是在一個函數內部建立l另外一個函數,經過另外一個函數訪問這個函數的局部變量git

主要應用閉包的場合:設計私有的方法和變量github

閉包的優勢

  1. 但願一個變量長期駐紮在內存中
  2. 避免全局變量的污染
  3. 私有成員的存在

閉包的缺點

閉包會使得函數中的變量都被保存在內存中,內存消耗很大,因此不能濫用閉包,不然會形成網頁的性能問題。瀏覽器

在IE中可能致使內存泄露。解決方法是,在退出函數以前,將不使用的局部變量所有刪除。閉包

在 IE8 如下的版本里,DOM 對象常常會跟 JavaScript 之間產生循環引用。就會形成內存泄漏:函數

function closure() {
    var element = document.getElementById('someElement');
    element.onclick = function(){
        alert(element.id) // 這裏致使element一直存在內存中
    }
}

應該將element解除引用來避免內存泄漏性能

function closure() {
    var element = document.getElementById('someElement');
    var test = element.id
    element.onclick = function(){
        alert(test) // 這裏致使element一致存在內存中
    }
    element = null
}

JavaScript 的垃圾回收機制

看完內存泄漏須要瞭解下JavaScript的垃圾回收機制,首先JavaScript具備自動垃圾回收機制,會找出再也不使用的變量,而後釋放其佔用的內存。經常使用的方法有兩種,即標記清除引用計數設計

引用計數

語言引擎有一張引用表,保存了內存裏面全部的資源(各類值)的引用次數。若是一個值的引用次數爲0,就表示這個值再也不用到了,所以就能夠將這塊內存釋放。可是引用計數有個最大的問題: 循環引用。code

function func() {
    let obj1 = {};
    let obj2 = {};

    obj1.a = obj2; // obj1 引用 obj2
    obj2.a = obj1; // obj2 引用 obj1
}

當函數 func 執行結束後,返回值爲 undefined,因此整個函數以及內部的變量都應該被回收,但根據引用計數方法,obj1 和 obj2 的引用次數都不爲 0,因此他們不會被回收。對象

要解決循環引用的問題,最好是在不使用它們的時候手工將它們設爲空。上面的例子能夠這麼作:ip

obj1 = null;
obj2 = null;

標記清除

JavaScript 中有個全局對象,瀏覽器中是 window。按期的,垃圾回收期將從這個全局對象開始,找全部從這個全局對象開始引用的對象,再找這些對象引用的對象...對這些活着的對象進行標記,這是標記階段。清除階段就是清除那些沒有被標記的對象。

總結

閉包只會在IE8如下的版本中才有可能形成內存泄漏問題,在最新版本的瀏覽器中,能夠經過標記清除的方式處理掉內存泄漏,不過閉包的變量會常駐內存,會形成必定的性能問題。

原文地址:https://github.com/hu970804/L...

相關文章
相關標籤/搜索