JavaScript - 原始類型(Primitive)與物件類型(Object)
原始類型(Primitive)與物件類型(Object)的差別在於兩者儲存的位置以及儲存的值,原始類型存於 Call Stack 中且儲存實際值,物件類型存於 Heap 中且儲存對物件的參考地址。
原始類型(Primitive)
在 JavaScript 中的原始數據類型有 :
- String
- Number
- Boolean
- undefined
- null
- BigInt
- Symbol
call by value
原始數據類型操縱的值為實際的賦值(call by value) :
1 | let age = 2 |
上面程式碼中因為宣告的變數是原始數據類型,所以儲存於 Call Stack 中,首先宣告 age
變數,JS 以變數名稱創建唯一的標識符(Identifier),然後分配一塊記憶體並提供記憶體位址(Address),最後將賦值(Value) 2
存到記憶體中。
第二步宣告 oldAge
等於 age
,JS 先創建標識符,後分配到另一記憶體位置,再將 age
的值存入記憶體。
最後,將 age
重新賦值為 3
,JS 通過唯一的標識符,取得儲存 age
的記憶體位址,再將原來的 2
改成 3
。
在 JS 引擎中 :
物件類型(Object)
在 JavaScript 中的物件類型有 :
- Object
- Function
- Array
call by reference
物件類型操縱的值為對物件的參考地址(call by reference) :
1 | const aben = { |
上面程式碼中,首先宣告 aben
物件,此物件會直接儲存在 Heap 裡面,JS 在 Call Stack 中創建唯一標識符 aben
,分配記憶體空間,而裡面儲存的值為對 Heap 中物件記憶體位址的參考(reference)。
再來,宣告 black
物件等於 aben
物件,JS 同樣創建唯一標識符,分配記憶體空間,同樣儲存 Heap 中 aben
物件記憶體位址的參考,也就是說 black
與 aben
都指向同一物件。
最後 black
物件修改 age
值,因為 black
與 aben
實際上都指向同一物件,所以最終兩者都改為 3
。
在 JS 引擎中 :
call by sharing
讓作為參數傳入的物件與函式中的參數物件共享同一物件。
看看下面的範例 :
1 | const aben = { |
aben
物件竟然還是原來的值,若物件類型是 call by reference 的話,aben
應該要大一歲才對。
這是因為當 aben
物件作為參數傳入函式時,是讓函數中的 obj
參數與 aben
共享一個物件,若是使用 obj.age
的方式重新賦值,那 aben
的年齡確實會改變,但是實際上在函式中卻是將一個新的物件賦值給 obj
參數,這樣 obj
與 aben
就指向不同的物件,也就是說函式執行後另外創建了一個物件,因此 aben
的年齡並沒有改變。