javascript內存管理

內存生命週期

程序語言的內存生命走起基本上都是一致的:javascript

  1. 分配你所需的內存;
  2. 使用分配到的內存(讀,寫);
  3. 不須要時將其釋放。

值的初始化

javascript在定義變量時就完成了內存的分配。

var n = 123; // 給數值變量分配內存
var s = "azerty"; // 給字符串分配內存

var o = {
  a: 1,
  b: null
}; // 給對象及其包含的值分配內存

// 給數組及其包含的值分配內存(就像對象同樣)
var a = [1, null, "abra"]; 

function f(a){
  return a + 2;
} // 給函數(可調用的對象)分配內存

// 函數表達式也能分配一個對象
someElement.addEventListener('click', function(){
  someElement.style.backgroundColor = 'blue';
}, false);複製代碼

經過函數調用分配內存

var d = new Date(); // 分配一個 Date 對象

var e = document.createElement('div'); // 分配一個 DOM 元素複製代碼

垃圾回收

垃圾回收算法主要依賴於引用的概念。在內存管理的環境中,一個對象若是有訪問另外一個對象的權限(隱式或者顯式),叫作一個對象引用另外一個對象。例如,一個Javascript對象具備對它原型的引用(隱式引用)和對它屬性的引用(顯式引用)。
java

如下實例是一個簡單的垃圾收集算法。此算法把「對象是否再也不須要」簡化爲「對象有沒有其餘對象引用到它」。若是沒有引用指向該對象(零引用),對象將被垃圾回收機制回收。算法

var o = { 
  a: {
    b:2
  }
}; 
// 兩個對象被建立,一個做爲另外一個的屬性被引用,另外一個被分配給變量o
// 很顯然,沒有一個能夠被垃圾收集


var o2 = o; // o2變量是第二個對「這個對象」的引用

o = 1;      // 如今,「這個對象」的原始引用o被o2替換了

var oa = o2.a; // 引用「這個對象」的a屬性
// 如今,「這個對象」有兩個引用了,一個是o2,一個是oa

o2 = "yo"; // 最初的對象如今已是零引用了
           // 他能夠被垃圾回收了
           // 然而它的屬性a的對象還在被oa引用,因此還不能回收

oa = null; // a屬性的那個對象如今也是零引用了
           // 它能夠被垃圾回收了複製代碼

循環引用

在下面的例子中,兩個對象被建立,並互相引用,造成了一個循環。它們被調用以後會離開函數做用域,因此它們已經沒有用了,能夠被回收了。然而,引用計數算法考慮到它們互相都有至少一次引用,因此它們不會被回收。
數組

function f(){
  var o = {};
  var o2 = {};
  o.a = o2; // o 引用 o2
  o2.a = o; // o2 引用 o

  return "azerty";
}

f();複製代碼

另外一個例子bash

var div;
window.onload = function(){
  div = document.getElementById("myDivElement");
  div.circularReference = div;
  div.lotsOfData = new Array(10000).join("*");
};複製代碼

在上面的例子裏,myDivElement 這個 DOM 元素裏的 circularReference引用了myDivElement ,形成了循環引用。若是該屬性沒有顯示移除或者設爲 null,引用計數式垃圾收集器將老是且至少有一個引用,並將一直保持在內存裏的 DOM 元素,即便其從DOM 樹中刪去了。若是這個 DOM 元素擁有大量的數據 (如上的 lostOfData 屬性),而這個數據佔用的內存將永遠不會被釋放。
函數

相關文章
相關標籤/搜索