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 的年齡並沒有改變。