[原]詳細分析 javascript 的內存分配

JavaScript語言是一門優秀的腳本語言.其中包含腳本語言的靈活性外還擁有許多高級語言的特性.例如充許構建和實例化一個對象,垃圾回javascript

收機制(GC:Garbage Collecation).一般咱們使用new建立對象,GC負責回收對象佔用內存區域.所以瞭解GC,能夠加深對JavaScript垃圾回收html

機制的理解。java

1.用局部變量和全局變量解釋GC程序員

GC在回收內存時,首先會判斷該對象是否被其它對象引用.在肯定沒有其它對象引用便釋放該對象內存區域.所以如何肯定對象再也不被引用是算法

GC的關鍵所在.數組

1.  <script>  數據結構

2.          function aa(){  函數

3.              this.rr = "彈窗";      this

4.          } spa

5.          function bb(){  

6.          this.rr = "彈窗";  

7.          } 

8.   

9.          var b1;  

10.         function cc(){  

11.             var a1 = new aa();  

12.             b1 = new bb();  

13.                     return b1;  

14.         } 

15.  

16.         cc(); 

17.         alert(b1.rr) 

18.     </script> 

如上代碼中,執行完cc()後a1被回收了,此後咱們能夠經過b1.rr彈出文字窗口.在一些基礎書籍中解釋爲:a1爲局部變量,b1是全局變量.局部

變量執行完後會被GC回收.但不全是這樣,以下代碼:

1.  <script>  

2.          function aa(){  

3.              this.rr = "彈窗";      

4.          } 

5.          function bb(){  

6.              this.rr = "彈窗";  

7.          } 

8.   

9.          function cc(){  

10.             var a1 = new aa();  

11.             var b1 = new bb();  

12.                 return b1;  

13.         } 

14.  

15.         var b1 = cc();  

16.         alert(b1.rr); 

17.     </script> 

此時cc函數中的 a1,b1都是局部變量,但仍然會彈出文字窗口.說明b1並無被GC回收.所以JavaScript中局部變量不是全部時候都被GC回收的.

2.抽象理解GC

GC回收機制還須要近一步瞭解。在此時引入幾個概念:雙向鏈表,做用域鏈,活動對象(爲了方便理解,簡化了原文的概念

[http://softbbs.pconline.com.cn/9497825.html]), 其中雙向鏈表描述複雜對象的上下層級關係. 做用域鏈與活動對象分別是雙向鏈表

中的某個節點.以函數cc爲例變量層級關係爲:

1.  window<=>cc<=>a1<=>rr 

2.                          <=>b1<=>rr 

(原文有詳細解釋)在執行cc()方法時,內存中變量的引用關係如上圖,文字解釋以下:

window的活動對象包括cc,假設window是頂級對象(由於運行中不會被回收)

cc的活動對象包括a1和b1,其做用域鏈是window

a1的活動對象包括rr,其做用域鏈是cc

b1的活動對象包括rr,其做用域鏈是cc

執行cc()時,cc的執行環境會建立一個活動對象和一個做用域鏈.其局部變量a1,b1都會掛在cc的活動對象中.當cc()執行完畢後,執行環境

會嘗試回收活動對象佔用的內存.但因局部變量b1 經過return b1,爲其增長了一條做用域鏈:window<=>b1<=>rr,因此GC中止對b1回收.

所以若是想將一個局部變量/函數提高爲全局的,爲其增長一條做用域鏈就OK了。

同時控制好對象的做用域鏈也變得重要了.因做用域鏈會意外致使GC沒法回收目標對象.例如:

1.  <SCRIPT LANGUAGE="JavaScript">  

2.        <!-- 

3.      // 

4.      function cat(name){  

5.          var zhuren ;  

6.          this.name = name;  

7.           

8.          //設置主人 

9.          this.addZhuRen = function(zr){  

10.             zhuren = zr; 

11.         } 

12.  

13.         this.getZhuRen = function(){  

14.             return zhuren;  

15.         } 

16.     }  

17.       

18.     //主人 

19.     function zhuren(name){  

20.         this.name = name;  

21.     }  

22.  

23.     //建立主人:  

24.     var zr = new zhuren("zhangsan");  

25.     //建立貓 

26.     var cat1 = new cat("asan");  

27.     //設置該貓的主人 

28.     cat1.addZhuRen(zr); 

29.     //釋放主人 

30.     zr = null ;  

31.     //此處還存在對主人對象的引用 

32.     alert(cat1.getZhuRen().name) 

33.       //-->  

34.   </SCRIPT> 

 

 

 

瞭解javascript的人都知道數據的基本類型按大的分類有兩種:原始值和引用值

  在研習算法的時候會過多的和內存打交道;理解棧和堆的定義是很重要的,算法就是爲了可以得到最大的效率

  任何語言都是如此,javascript也不例外;在javascript中,我在把變量類型分爲原始類型和引用類型。原始類型是放在棧即內存中,而引用類型這是放在堆中。在ECMAscript中,也是這麼定義的。

  棧

主要做用表現爲一種數據結構,是隻能在某一端插入和刪除的特殊線性表。它按照後進先出的原則存儲數據,先進入的數據被壓入棧底,最後的數據在棧頂,須要讀數據的時候從棧頂開始彈出數據(最後一個數據被第一個讀出來)。

   棧是容許在同一端進行插入和刪除操做的特殊線性表。容許進行插入和刪除操做的一端稱爲棧頂(top),另外一端爲棧底(bottom);棧底固定,而棧頂 浮動;棧中元素個數爲零時稱爲空棧。插入通常稱爲進棧(PUSH),刪除則稱爲退棧(POP)。棧也稱爲後進先出表。在這裏用數組進行模擬棧的特性

  棧能夠用來在函數調用的時候存儲斷點,作遞歸時要用到棧!

 

?

var arr=[];//建立一個數組模擬棧

arr.push("a");//壓入元素a

arr.push("b");//壓入元素b

arr.pop();//彈出元素a

arr.pop();//彈出元素b

arr.push("c");//壓入元素c

 

 圖譜解釋:

 

從上圖能夠看出棧有着先進後出的特性;在棧中的數據直接能夠訪問,效率比較高

 

  堆:

在程序中,堆用於動態分配和釋放程序所使用的對象。在如下狀況中調用堆操做:

    1.事先不知道程序所需對象的數量和大小。

    2.對象太大,不適合使用堆棧分配器。

  堆使用運行期間分配給代碼和堆棧之外的部份內存。

   在javascript中,引用數據是放在堆中的,例如數組和對象,由於在javascript中,一切都是對象,對象能夠進行擴展,放置在堆中能夠進 行不斷的擴展,若是放在內存中就會消耗大量資源。放置在堆中的數據的查詢效率比較低。這也是內存優於堆的好處,可是內存的存儲空間要比堆的小不少。

 

?

function Car(id,name,price)

{

    this.id=id;

    this.name=name;

    this.price=price;

}

var num=24;

var str="car";

var bol=false;

var obj={};

var arr=[1,2,3];

var car=new Car(1,"benze",230000);

 

 圖譜解釋:

這樣很清楚的知道棧和堆的區別;原始類型的數據放在棧中,引用類型的數據放在堆中。引用類型的數據同C中的指針很相似,咱們不能直接操做堆中的數據,咱們經過一個指針來引用這些數據進行操做,看以看做是遠程操控。

    棧與堆的區別:

1 效率的不一樣

      棧的效率比堆要高,棧中的數據直接可使用,而對則須要經過引用來進行操做,即棧的速度比堆快

2 空間存儲不一樣

                堆的存儲空間要比棧大

          3 放置數據類型的不一樣

 

相關文章
相關標籤/搜索