JavaScript變數儲存淺析(二)

大魔王薩格拉斯發表於2015-11-17

Hello,上一篇(http://www.cnblogs.com/souvenir/p/4969399.html)我們簡單的分享了JS中的變數儲存原理,但是並未結束,我們漏掉了什麼。

對了,就是關於物件的儲存。

 

  大家都知道,JavaScript中的變數型別分為兩種,一種是基本資料型別,包括:undefined,null,Number,String,Boolean,另外一種就是物件。

  兩種資料型別的儲存方式在JS中也有所不同。

  另外,記憶體分為棧區(stack)和堆區(heap),然後在JS中開發人員並不能直接操作堆區,堆區資料由JS引擎操作完成,那這二者在儲存資料上到底有什麼區別呢?

  我們簡單的通過下面這張圖來分析:

  

  JS中變數的定義在記憶體中包括三個部分:

    •   變數標示  (比如上圖中的Str,變數標示儲存在記憶體的棧區)
    •   變數值     (比如上面中的Str的值souvenir或者是obj1物件的指向堆區地址,這個值也是儲存在棧區)
    •       物件        (比如上圖中的物件1或者物件2,物件儲存在堆區)

  也就是說,對於基本資料型別來說,只使用了記憶體的棧區。

 

  對於上一篇中提到的問題來說,

1 var a = 100;     
2  
3 func();
4 
5 function func(){
6     console.log(a);
7     var a=200;        
8     console.log(a);
9 }

  在JS預載入階段,JS引擎只是在記憶體的棧區為每個變數分配了記憶體,指定了標示符,並未為其指定值。

  等到JS執行期才會為其賦值。

 

  現在我們再來看物件變數的問題就比較清楚了,例如下面的:

 1 var a=100;
 2 var obj1={
 3     attr:'hello'
 4 };
 5 
 6 func(a,obj1);
 7 
 8 function func(num,obj){
 9     var a2=num;
10     a2=200;
11     
12     var obj2=obj;
13     obj2.attr='hello';
14 }
15 
16 console.log(a);
17 console.log(obj1.attr);

  我們分別定義了一個基本型別和物件型別的變數,然後在函式中對其分別執行復制操作,然後修改新變數的值。

  最後的執行結果為:

  

  對於基本資料型別,在執行第9行時,JS是把num在棧區的值,也就是100複製給了a2這個區域性變數,然後在第10行又修改了a2的值,

  這個操作過程並未影響到全域性變數a的值。

 

  小結:

  對於物件來說,當JS執行12行的時候,實際上是把obj在棧區的值,也就是obj物件在堆區的引用地址,複製給了新的區域性變數obj2,

  這時候,obj2與obj實際上已經指向了同一個堆區的物件,然後obj2修改了這個物件的某個屬性值。然後函式執行完畢,obj2這個區域性變數沒有引用將會被GC回收。

  再次訪問obj1這個全域性變數時,其所指向的物件其實已經被修改過了。

 

  

相關文章