廢話片:
講到內存可以聯想到很多,內存分配管理,內存回收機制,內存泄露等等,今天我們就來答題的總結一下。
正文片:
1.內存分配管理
2.內存回收機制
3.內存泄露
一、內存分配管理
首先讓我們看看內存的分配機制吧。其實在所有的語言中內存的分配都是一樣的,首先在我們需要的時候記性內存的分配,然后是使用分配的內存,最后是當我們不適用的時候收回內存塊。
問題:在js中是如何分配內存的呢,什么時候分配呢?
回答:在js中當我們定義了變量的時候實際上就為我們分配好了內存的,這樣將會省去我們的很多麻煩。了如如下:
1 // 給數值變量分配內存 2 var n = 123; 3 // 給字符串分配內存 4 var s = "azerty"; 5 6 // 給對象及其包含的值分配內存 7 var o = { 8 a: 1, 9 b: null 10 }; 11 12 // 給數組及其包含的值分配內存(就像對象一樣) 13 var a = [1, null, "abra"]; 14 15 // 給函數(可調用的對象)分配內存 16 function f(a){ 17 return a + 2; 18 } 19 20 // 函數表達式也能分配一個對象 21 someElement.addEventListener('click', function(){ 22 someElement.style.backgroundColor = 'blue'; 23 }, false);
當然,還有其他的也寫情況實際上也是需要系統為我們分配內存的,例如當我們使用構造函數來定義一個新的對象的時候,我們是需要對新的對象討要空間的。
1 var d = new Date(); // 分配一個 Date 對象 2 var e = document.createElement('div'); // 分配一個 DOM 元素
有的時候我們需要對於數據進行組合或是在原有的數據上進行值的設置,這時系統也會為我們新分配一塊內存區域。
1 var s = "azerty"; 2 var s2 = s.substr(0, 3); // s2 是一個新的字符串 3 // 因為字符串是不變量 4 // JavaScript 可能沒有分配內存 5 // 但只是存儲了 [0-3] 的范圍。 6 7 var a = ["ouais ouais", "nan nan"]; 8 var a2 = ["generation", "nan nan"]; 9 var a3 = a.concat(a2); 10 // 新數組有四個元素,是 a 連接 a2 的結果
問題:內存空間使用?
回答:當系統為我們分配了內存空間之后我們實際上在每一次對於當前的值得操作的時候都是使用了這一內存塊,讀取和寫入操作將會是我們對於內存塊的基礎操作。
二、內存回收機制
問題:js的內存是如何回收的?
回答:js是具有自動垃圾收集機制的,這種機制會自動的跟蹤每一個變量的動向,並判斷當前的變量是否還有存在的必要,然后將不必要的變量所占用的內存進行收回。對於這樣的收回機制,實際真正的運用起來是有兩種不同的方法來實現的。詳情見如下:
1.方法一:標記清除算法
這一算法是為進入環境中的變量標記一個“進入環境”的標記。邏輯上講呢,當我們的變量進入環境的時,變量實際上是不應該被刪除的,因為上下文中可能會用到當前的變量進行相關的邏輯演算,而當變量離開環境的時候,竟會為其標記成為“離開環境”的狀態。
2.方法二:引用計數
引用對象是放在堆中的,而這一內存清理方法是對這一值的引用次數進行統計,當我們聲明了一個變量,並且將引用對象的值賦值給了這一變量,則引用對象的引用計數加 一,反之當我們的引用對象的相關引用變量其指向的內容發生了變化,則引用對象的引用計數減一。當引用對象的引用計數為0的時候這表明,此對象值可回收。
以上其實就是最為常用的內存回收機制,當然我們的內存回收機制是在一定的時間間隔后,自動的運行的,每次都會搜尋是否有變量可以收回,並回收內存。
三、內存泄漏
內存泄漏是指在我們編碼的過程中,有的某一些操作是的當前的內存塊即使不在會被使用到,釋放機制也因為辨別不出(bug啦)是否需要釋放而使得這一不需要的變量得以保留。雖然對於有內存回收機制的js和java是很少有這種情況發生的。但是。。。你懂得,下面就來看一看有哪些情況會導致這一情況
1、當我們在IE中使用.onclick的時候如果我們沒有手動的刪除這一事件則會造成和內存泄漏(IE果然好坑啊)
1 document.getElementById("xxx").onclick = fuction(){}; 2 //在IE中是不會自動的回收內存的。 3 4 //改進方法 5 document.getElementById("xxx").onclick = fuction(){ 6 document.getElementById("xxx").onclick = null; 7 ....... 8 }; 9 10 //或者使用 11 document.getElementById("xxx").addEventListener(......);
2、當我們對於DOM對象使用循環引用的情況下,js的回收機制就沒有辦法回收了。
1 var a = document.getElementById("xxx"); 2 a.r = a;
3、必報在編寫過程中的時候是經常要使用到的一個概念。但是但我們在閉包中定義了響應時間的時候就會造成一定量的內存占用。
1 function bindEvent() 2 { 3 var obj=document.createElement("XXX"); 4 obj.onclick=function(){ 5 //Even if it's a empty function 6 } 7 }//這樣閉包內的obj元素回因為其中的onclick時間的綁定而沒有辦法進行釋放,這樣就造成了運行時的內存浪費。
4、某些代碼不嚴謹可能導致內存泄漏
1 a = {p: {x: 1}}; 2 b = a.p; 3 delete a.p;//a中的元素實際上已已經刪除了,可是被刪除的元素並沒有清空,因為外部中變量b指向了這一元素數據。這樣就可能造成內存的浪費
5、最后,我們在來黑IE一把,實際上在IE中有一些DOM操作或者是屬性轉化的操作會造成相關的內存泄漏的風險,所以說我們在編寫適配IE瀏覽器的時候還是要更為的注意一些的啊。
內存泄漏的情況絕對不僅僅是我上面說的着一些,在我們的平時編寫代碼的過程中我們可以找到更多的這樣的bug並對其進行相關的優化,將會使得我們的代碼更為的良好而健壯。
