[JS奇怪的世界]No.28 觀念小叮嚀:傳值和傳參考

前言

我們即將深入瞭解 JavaScript 中其中一個很常遇到的東西,傳值 (by value) 及傳參考 (by reference),這個觀念很重要,所以若對於這觀念不清楚,將會導致後續開發上及 debug 上的困擾。

傳值 (by value)

傳值其實很簡單,讓我們從範例來了解 ↓

1
2
3
4
var a = 2;
b = a;
console.log(a);
console.log(b);

b 會去尋找 a 的記憶體位址,然後複製填上相同的值到 b 並得到新的記憶體位址,而這個過程就是傳值 (by value)

by value

傳參考 (by reference)

這邊要講的這個東西就比較常見了,如果在 JavaScript 中有一個物件,當設定變數為一個物件一樣可以取的一個記憶體位址,但當 b 等於 a 的意思其實是我們試著讓這兩個東西一樣,所以 b 並不會得到新的記憶體位址,而這就是傳參考 (by reference)。

by reference

所有物件都是傳參考 (by reference)特性。

範例傳值 (by value)

這邊先來看看傳值 (by value) 的範例 ↓

1
2
3
4
var a = 3;
var b;

b = a;

這邊要記得一個重點,只要不是物件,那就是在傳值 (by value) 因為 3 是一個純值一個數值,所以 b 會 copy a 的值並且建立一個新記憶體位址,所以若我們這樣做並不會影響到 b

1
2
3
4
5
6
7
var a = 3;
var b;

b = a;
a = 10;
console.log(a);
console.log(b);

而這就是所謂的傳值 (by value)

範例傳參考 (by reference)

首先先準備一個物件範例 ↓

1
2
3
var c = { greeting: 'hi' };
var d;
d = c;

當執行程式碼時會發生什麼事情?d會知道它後面帶入的是一個物件 (Object),所以並不會建立新的記憶體位址,而是直接讓 d 指向與 c 相同的記憶體位址,雖然輸出時可以看到相同的東西,但是在記憶體指向是相同的,所以如果這樣做 ↓

1
2
3
4
5
6
7
var c = { greeting: 'hi' };
var d;
d = c;
c.greeting = 'hello';

console.log(c.greeting);
console.log(d.greeting);

我們可以看到 d 也跟著變了。

by reference

這就是所謂的傳參考 (by reference,而 c.greeting = 'hello'; 這過程稱之為 mutate。

by reference

所以當等號運算子知道你要改變某個值的時候,它就會去改變 (mutate)。

mutate 就是改變某個東西的意思,當我們說 I mutate my object,就是代表著我要改變它 (Object),所以我們可以知道一件事情,不論我們在哪一行做修改,都會導致 d 被改變,原因是它們都是指向同一個記憶體。

例外狀況

這邊還需要知道一件事情,等號運算子可以設定一個新記憶體空間,當若我們是使用這種方式去修改的話 ↓

1
2
3
4
5
6
7
var c = { greeting: 'hi' };
var d;
d = c;
c = { greeting: 'hello' };

console.log(c);
console.log(d);

例外狀況

這樣做 dc 就不會指向同一個記憶體位子,那這是一個特殊狀況。

圖源

JavaScript 全攻略:克服 JS 奇怪的部分

0%