什麼是內存泄漏?什麼操作會觸發內存泄漏?

內存泄漏是指 一些對象我們不在使用它的時候,他任然存在
setTimeout 的第一個參數使用字符串而非函數的話,會引發內存泄漏
閉包使用不當

什麼是閉包(Closure)

簡單講,閉包就是指有權訪問另一個函數作用域中的變量的函數。
它由兩部分構成:函數,以及創建該函數的環境。環境由閉包創建時在作用域中的任何局部變量組成。

這種官方的概念是比較難理解的,在面試的時候說出來也不是很專業,因爲沒辦法有個具體的邏輯。

我個人認爲,理解閉包的關鍵在於:外部函數調用之後其變量對象本應該被銷燬,但閉包的存在使我們仍然可以訪問外部函數的變量對象,這就是閉包的重要概念。

function outer(){
var a=1;
return function(){
        return a;
  }
}
var b=outer()
console.log(b())

產生一個閉包
創建閉包最常見方式,就是在一個函數內部創建另一個函數。下面例子中的 closure 就是一個閉包:

funciton func(){
  var a =1,b = 2;
      function closure(){
          return a+b;
        }
    return closure;
}

閉包的作用域鏈包含着他自己的作用域,以及包含它的函數的作用域和全局作用域。

閉包的注意事項

.通常,函數的作用域及其所有變量都會在函數執行結束後被銷燬。但是,在創建了一個閉包以後,這個函數的作用域就會一直保存到閉包不存在爲止。

function makeAdder(x){
return function(y){
return x+y
    };
}
var add5 = makeAdder(5);
var add10 = makeAdder(10);
console.log(add5(5)); //此處爲10
console.log(add10(10))//此處爲20
//在下面釋放對閉包的引用
addd5=null;
add10=null;

從上述代碼可以看到add5 和 add10 都是閉包。它們共享相同的函數定義,但是保存了不同的環境。在 add5 的環境中,x 爲 5。而在 add10 中,x 則爲 10。最後通過 null 釋放了 add5 和 add10 對閉包的引用。

在javascript中,如果一個對象不再被引用,那麼這個對象就會被垃圾回收機制回收;

如果兩個對象互相引用,而不再被第3者所引用,那麼這兩個互相引用的對象也會被回收。

閉包只能取得包含函數中的任何變量的最後一個值

function arrFunc(){
    var arr=[];
for(var i=0;i<10;i++){
arr[i]=function(){
              }
         }
    return arr;
}
大家看一下上面這個代碼,arr數組中包含了10個匿名函數,每個匿名函數都能訪問外部函數的變量i,那麼i是多少呢?

當arrFunc執行完畢後,其作用域被銷燬,但它的變量對象仍保存在內存中,得以被匿名訪問,這時i的值爲10。

要想保存在循環過程中每一個i的值,需要在匿名函數外部再套用一個匿名函數,在這個匿名函數中定義另一個變量並且立即執行來保存i的值。

下面是結論內存泄漏的一些方法

1、給DOM對象添加的屬性是一個對象的引用。範例: 
var MyObject = {}; 
document.getElementById('myDiv').myProp = MyObject; 
解決方法: 
在window.onunload事件中寫上: document.getElementById('myDiv').myProp = null; 
2、DOM對象與JS對象相互引用。範例: 
function Encapsulator(element) { 
this.elementReference = element; 
element.myProp = this; 
} 
new Encapsulator(document.getElementById('myDiv')); 
解決方法: 
在onunload事件中寫上: document.getElementById('myDiv').myProp = null; 
3、給DOM對象用attachEvent綁定事件。範例: 
function doClick() {} 
element.attachEvent("onclick", doClick); 
解決方法: 
在onunload事件中寫上: element.detachEvent('onclick', doClick); 
4、從外到內執行appendChild。這時即使調用removeChild也無法釋放。範例: 
var parentDiv = document.createElement("div"); 
var childDiv = document.createElement("div"); 
document.body.appendChild(parentDiv); 
parentDiv.appendChild(childDiv); 
解決方法: 
從內到外執行appendChild: 
var parentDiv = document.createElement("div"); 
var childDiv = document.createElement("div"); 
parentDiv.appendChild(childDiv); 
document.body.appendChild(parentDiv); 
5、反覆重寫同一個屬性會造成內存大量佔用(但關閉IE後內存會被釋放)。範例: 
for(i = 0; i < 5000; i++) { 
hostElement.text = "asdfasdfasdf"; 
} 
這種方式相當於定義了5000個屬性! 
解決方法: 
其實沒什麼解決方法:就是編程的時候儘量避免出現這種情況咯~~ 

以上就是個人對閉包及內存泄漏的見解不周,望各位看客多多包涵

發佈了30 篇原創文章 · 獲贊 26 · 訪問量 6530
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章