傳值 (Pass by value)
在 JavaScript 中,當變數的值是原生型別時,就是傳值
如果傳遞的變數是原生型別時,傳遞的就會是值的複本,而不是傳遞變數的記憶體位置。我們可以使用 =
來賦予變數一個值舉以下的例子,分別賦予不同數字給 a
、b
:
可以注意到第 2 行,將 b
指定為 a
的值 +1,這時候 c
的值就會是 1 + 1 = 2
,非常直覺也很好理解,這就是所謂的「傳值(Pass by value)」
傳址 (Pass by reference)
在 JavaScript 中,當變數不是原生型別時,就是傳址
當變數是物件或陣列的情況下,JavaScript 會需要額外的紀錄代表其記憶體位置,因此變數內儲存的並不是實際的內容,而是一個內容所在的記憶體位置。舉以下圖表為例,圖表中的 b
變數實際上持存的是記憶體位址:
變數 | 值 |
---|---|
a | 1 |
b | 0x01 |
記憶體位址 | 值 |
---|---|
0x01 | [1,2] |
了解了傳址的概念後,我們來延伸前面的例子,如果這時候有個變數 c = b
那麼畫成圖表就會是這樣:
變數 | 值 |
---|---|
a | 1 |
b | 0x01 |
c | 0x01 |
記憶體位址 | 值 |
---|---|
0x01 | [1,2] |
如此一來 b
與 c
所指向的記憶體位置都是 0x01
,因此當我們對 c
做修改時,b
也會跟著改變:
這也是為什麼 b
與 c
的值都會變成 [1, 2, 3]
,因為 b
與 c
都指向了同一個記憶體位置。
相等但不相等
了解前面傳值與傳址的差異後,會發現記憶體位置與值是全然不同的東西,一個是指標,一個是內容,實際就像以下圖表範例。
變數 | 值 |
---|---|
a | 0x01 |
b | 0x02 |
記憶體位址 | 值 |
---|---|
0x01 | [1,2] |
0x02 | [1,2] |
變數 | 值 |
---|---|
a | 0x01 |
b | 0x01 |
記憶體位址 | 值 |
---|---|
0x01 | [1,2] |
總結
了解 JavaScript 是如何儲存變數有助於更好的操控資料,避免出現改 A 卻動到 B 的狀況。