由於字符串、對象和數組沒有固定的大小,因此只有在知道動態存儲分配的大小時才能執行。每次JavaScript程序建立字符串、數組或對象時,解釋器必須分配內存來存儲該實體。只要像這樣動態地分配內存,它最終將被釋放以即可以重用,不然JavaScript解釋器將消耗系統中的全部可用內存並致使系統崩潰。javascript
這篇文章解釋了爲何系統須要垃圾收集。與C/C++不一樣,JS有本身的垃圾收集機制。javascript解釋器能夠檢測程序什麼時候再也不使用對象。當他肯定一個物體是無用的時,他知道它再也不須要了,能夠釋放它所佔據的記憶。例如:java
var a=以前;
var b=覆蓋a;
var a=b;//重寫a
運行此代碼後,「before」字符串將丟失其引用(之前由a引用)。當系統檢測到這個事實時,它會釋放字符串的存儲空間,以即可以重用。數組
二。垃圾回收利用原理分析瀏覽器
如今,主要瀏覽器一般使用兩種垃圾收集方法:標籤清除和引用計數。dom
1。標記間隙函數
這是JavaScript中最多見的垃圾收集方式。當變量進入執行環境時,它被標記爲入口環境。從邏輯上講,進入環境的變量永遠沒法從內存中釋放,由於只要執行流進入相應的環境,就可使用它們。當變量離開環境時,它被標記爲「離開環境」。
當垃圾收集器運行時,它標記存儲在內存中的全部變量。而後,它刪除環境中的變量和環境中變量引用的標記。以後標記的變量被視爲準備刪除,由於環境中的變量再也不可訪問。最後。垃圾收集器執行內存清理、銷燬標記值並回收它們佔用的內存。對象
對於這一部分,我建議閱讀湯姆叔叔的文章,詳細解釋一些關於範圍鏈的知識。在閱讀以後,您幾乎能夠知道哪些變量將被標記。ip
2。參考計數內存
另外一種不太常見的垃圾收集策略是引用計數。引用計數意味着跟蹤每一個值被引用的次數。當變量被聲明而且引用類型被分配給該變量時,對該值的引用數爲1。相反,若是包含對該值的引用的變量生成另外一個值,則對該值的引用數將減小1。當引用數爲零時,意味着沒法再次訪問該值,所以能夠恢復它所佔用的內存空間。這樣,下次垃圾收集器運行時,它將釋放具備零引用的值所佔用的內存。element
可是這個方法有問題。讓咱們看看下面的代碼。
複製代碼
函數問題()。{
var obja=新對象();
var objb=新對象();
obja.someOtherObject=objb;
objb.anotherObject=obja;
}
複製代碼
在本例中,obja和objb經過各自的屬性相互引用;垃圾分類也就是說,對兩個對象的引用數爲2。在使用引用計數策略中,因爲兩個對象在函數執行後都離開做用域,所以在函數執行後,obja和objb將繼續存在,由於它們的引用數永遠不會爲零。若是大量存在這樣的交叉引用,可能會致使大量內存泄漏。
咱們知道IE中的一些對象不是本機JavaScript對象。例如,它們的BOM和DOM中的對象使用C++到COM(組件對象)。
模型(組件對象)以對象的形式實現,COM對象的垃圾收集器是引用計數策略。所以,即便IE的javascript引擎實現了標記清除,javascript仍是基於引用計數策略訪問COM對象。坦率地說,只要COM對象涉及到IE,就存在循環引用的問題。請看下面的簡單示例:
var元素=文檔。getElementByID(「some_element」);
var myobj=新對象();
MYOBJ.元素=元素;
元素。someObject=myobj;
在上面的示例中,在dom元素和本機javascript對象(myobj)之間創建循環引用。其中,變量myobj有一個名爲element的屬性指向元素,而變量元素有一個名爲someobject的屬性指向myobj。因爲循環引用,即便從頁面中刪除示例中的DOM,也不會回收內存。
可是,上述問題並不能解決,咱們能夠手動切斷它們的循環引用。
MYOBJ.元素=空;元素。someObject=空;這樣,T