傳值與傳參考

這堂課將介紹在 JavaScript 一個很重要的觀念,傳值 pass by value 和傳參考 (傳址) pass by referece

傳值 By Value

一段簡單的程式碼如下,首先,先宣告一個變數 a 並給它一個 primitive value 3,這時候 a 會存在記憶體中的一個位置 0x001 。接著宣告一個 b = ab 實際上會建立另一個記憶體位置 0x002,兩者的值並不會互相干擾,這種情況我們就稱為傳值 pass by value,這種情況只會發生在值為 primitive type 的變數上。

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

b = a;
a = 2;

console.log(a); // 2
console.log(b); // 3

傳址(傳參考) By Reference

相對的,如果宣告一個變數 a 並給它一個型別為物件 (Function 也是) 的值,同樣會在記憶體中給它一個位置 0x001 ;但當我們建立另一個變數 b ,並把 b 的值等同於 a,實際上不會在記憶體中再給它一個位置,變數 ab 都會指向相同的位置 0x001 ,所以當 a 的值給便時也會影響到 b,這種情況我們就稱為傳址 (傳參考) pass by reference

一段簡單的程式碼如下,當我們建立一個變數 c 並給它一個物件 object 的值,再建立一個 d 並讓它等於 c,接著更改 (mutate) c 的值時,d 也會跟著改變; 甚至我們透過一個函式來更改 c 的值時,d 也會跟著改變

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
var c = { greeting: "Hello" };
var d;

d = c;

console.log(c); // { greeting: "Hello" }
console.log(d); // { greeting: "Hello" }

c.greeting = "Hola";

console.log(c); // { greeting: "Hola" }
console.log(d); // { greeting: "Hola" }

function changeGreeting(obj) {
obj.greeting = "Hi";
}

changeGreeting(c);

console.log(c); // { greeting: "Hi" }
console.log(d); // { greeting: "Hi" }

例外

前面提到如果建立變數 c 並給予一個 object 的值,並新增另一個變數d 等於 c, 就會透過 pass by reference 的方式指向記憶體中的這個位置,但當我們透過 object literal 的方式重新賦予這個變數另外一個 object 的值時,JavaScript 會在記憶體中新增一個位置來存放這個新的物件,這時候 cd 就會分別指向記憶體中不同的 object

1
2
3
4
5
6
7
8
9
var c = { greeting: "Hello" };
var d;

d = c;

c = { gretting: "Hi" };

console.log(c); // { greeting: "Hi" }
console.log(d); // { greeting: "Hello" }

資料來源

Udemy-JavaScript: Understanding the Weird Parts