## 內存專題
> * `JAVASCRIPT`的內存回收機制
> * 以Google的`V8`引擎為例,在`V8`引擎中所有的`JAVASCRIPT`對象都是通過`堆`來進行內存分配的。當我們在代碼中`聲明變量`并`賦值`時,`V8`引擎就會在`堆內存`中分配一部分給這個`變量`。如果已申請的`內存`不足以存儲這個`變量`時,`V8`引擎就會繼續申請`內存`,直到`堆`的大小達到了`V8`引擎的內存上限為止(默認情況下,`V8`引擎的`堆內存`的大小上限在`64位系統`中為`1464MB`,在`32位系統`中則為`732MB`)。
> * 另外,`V8`引擎對`堆內存`中的`JAVASCRIPT`對象進行`分代管理`。
> * 新生代。
> * 新生代即存活周期較短的`JAVASCRIPT`對象,如臨時變量、字符串等
> * 老生代。
> * 老生代則為經過多次垃圾回收仍然存活,存活周期較長的對象,如主控制器、服務器對象等。
> * 垃圾回收算法。
> * 垃圾回收算法一直是編程語言的研發中是否重要的??一環,而`V8`引擎所使用的垃圾回收算法主要有以下幾種。
> * `Scavange`算法:通過復制的方式進行內存空間管理,主要用于新生代的內存空間;
> * `Mark-Sweep`算法和`Mark-Compact`算法:通過標記來對堆內存進行整理和回收,主要用于老生代對象的檢查和回收。
> * 對象進行回收。
>
>
> * `引用`。
>
>
> * 當函數執行完畢時,在函數內部所聲明的對象`不一定`就會被銷毀。
> * 引用(`Reference`)是`JAVASCRIPT`編程中十分重要的一個機制。
>
>
> * 是指`代碼對對象的訪問`這一抽象關系,它與`C/C++`的指針有點相似,但并非同物。引用同時也是`JAVASCRIPT`引擎在進行`垃圾回收`中最關鍵的一個機制。
>
>
>
> ~~~
> var val = 'hello world';
> function foo() {
> return function() {
> return val;
> };
> }
> global.bar = foo();
> ~~~
>
>
> * 當代碼執行完畢時,對象`val`和`bar()`并沒有被回收釋放,`JAVASCRIPT`代碼中,每個`變量`作為單獨一行而不做任何操作,`JAVASCRIPT`引擎都會認為這是對`對象`的訪問行為,存在了對`對象的引用`。為了保證`垃圾回收`的行為不影響程序邏輯的運行,`JAVASCRIPT`引擎不會把正在使用的`對象`進行回收。所以判斷`對象`是否正在使用中的標準,就是是否仍然存在對該`對象`的`引用`。
>
>
> * `JAVASCRIPT`的`引用`是可以進行`轉移`的,那么就有可能出現某些引用被帶到了全局作用域,但事實上在業務邏輯里已經不需要對其進行訪問了,這個時候就應該被回收,但是`JAVASCRIPT`引擎仍會認為程序仍然需要它。
> * `IE`下閉包引起跨頁面內存泄露。
> * `JAVASCRIPT`的內存泄露處理
>
>
> * 給`DOM`對象添加的屬性是一個對象的引用。
>
>
>
> ~~~
> var MyObject = {};
> document.getElementByIdx_x('myDiv').myProp = MyObject;
> ~~~
>
>
>
> 解決方法:在window.onunload事件中寫上:
>
>
>
> ~~~
> document.getElementByIdx_x('myDiv').myProp = null;
> ~~~
>
>
> * DOM對象與JS對象相互引用。
>
>
>
> ~~~
> function Encapsulator(element) {
> this.elementReference = element;
> element.myProp = this;
> }
> new Encapsulator(document.getElementByIdx_x('myDiv'));
> ~~~
>
>
>
> 解決方法:在onunload事件中寫上:
>
>
>
> ~~~
> document.getElementByIdx_x('myDiv').myProp = null;
> ~~~
>
>
> * 給DOM對象用attachEvent綁定事件。
>
>
>
> ~~~
> function doClick() {}
> element.attachEvent("onclick", doClick);
> ~~~
>
>
>
> 解決方法:在onunload事件中寫上:
>
>
>
> ~~~
> element.detachEvent('onclick', doClick);
> ~~~
>
>
> * 從外到內執行appendChild。這時即使調用removeChild也無法釋放。
>
>
>
> ~~~
> var parentDiv = document.createElement_x("div");
> var childDiv = document.createElement_x("div");
> document.body.appendChild(parentDiv);
> parentDiv.appendChild(childDiv);
> ~~~
>
>
>
> 解決方法:從內到外執行appendChild:
>
>
>
> ~~~
> var parentDiv = document.createElement_x("div");
> var childDiv = document.createElement_x("div");
> parentDiv.appendChild(childDiv);
> document.body.appendChild(parentDiv);
> ~~~
>
>
> * 反復重寫同一個屬性會造成內存大量占用(但關閉IE后內存會被釋放)。
>
>
>
> ~~~
> for(i = 0; i < 5000; i++) {
> hostElement.text = "asdfasdfasdf";
> }
> ~~~
>
>
>
> 這種方式相當于定義了5000個屬性,解決方法:無。
>
>
> * `內存`不是`緩存`。
> * 不要輕易將`內存`當作`緩存`使用。
> * 如果是很重要的資源,請不要直接放在`內存`中,或者制定`過期機制`,自動銷毀`過期緩存`。
> * `CollectGarbage`。
> * `CollectGarbage`是`IE`的一個特有屬性,用于釋放內存的使用方法,將該變量或引用對象設置為`null`或`delete`然后在進行釋放動作,在做`CollectGarbage`前,要必需清楚的兩個必備條件:(引用)。
> * 一個對象在其生存的上下文環境之外,即會失效。
> * 一個全局的對象在沒有被執用(引用)的情況下,即會失效