JavaScript 中的「傳值」 與 「傳址」


基本型別

假設我們有兩個變數ab分別設定為 10,接著把b的值等於a;最後再把a的值改為20

1
2
3
4
5
6
7
8
9
var a = 10;
var b = 10;
//在基本型別的時候,會認為這兩個變數的「值」是相等的,因為兩個變數的數值都是 10
console.log( a === b ); // true
a=20;
var c=a;
console.log("a is "+a); // a is 20
console.log("b is "+b); // b is 10
console.log("c is "+c); // c is 10

變數 c 的值是透過複製變數 a 的值而來。

但變數 a 更新之後,不會去影響變數 c 的數值。

表面上看起來變數 c 的內容是透過複製變數 a 而來,但此時若變數 a 的內容為基本型別時,實際上變數 c 是去建立了一個新的值,然後將變數 a 的內容複製了一份過來。

Call By Value

當我們在建立「基本型別」 的變數時,根據上面的例子,a 會存在記憶體中的某個位置。這時候,當我指定另一個變數 c,它的值等同於 a 的時候,c 實際上會建立另一個獨立的記憶體位置,接著再把 a 的值存在這個獨立的記憶體位置。也就是說, a 和 b 其實是存在於兩個不同的記憶體位置,因此彼此並不會乎相干擾影響,這種情況,我們就稱為 Call By Value

物件型別

JavaScript 的物件都應該看作是一個「實體」

1
2
3
4
5
6
7
8
9
10
11
var a= { value: 10 };

var b= { value: 10 };
//// a 與 b 不是同一個實體。
console.log( a === b ); // false

b=a;
a.value=20;
console.log(a.value); // 20
console.log(b.value); // 20
console.log( a === b ); // true

「物件」在 JavaScript 中是透過「引用」的方式傳遞資料的,當 a.value 的內容被更新了之後,連帶著 b.value 也跟著改變。

Call By Reference

當我將變數 a 設立成一個 Object 時,一樣會存在記憶體中的某個位置;但是當我建立一個變數 b,並且把變數 b 的值等同於 a 時,這時候並不會再給予它一個新的位置,而是將 b 指定到物件 a 的位置,讓變數 a 和 b 使用相同的記憶體位置,因此,當 a 的值改變的時候 b 的值也會改變,這種情形我們就稱為 Call By Reference

例外情況

如果使用 object literal 的方式指定物件的值,那麼就會是 Call by value:

1
2
3
4
5
6
7
8
9
var a= { value: 10 };

var b;

b=a;
a={value: 20};

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

在這種情況下,因為它並不清楚 a 的內容是已經存在的,所以會建立一個新的記憶體位置來存放 a 物件裡面的內容。

Call by sharing

JavaScript 實際上是另一種稱做「call by sharing」的模式,其特點在於,當 function 的參數,如 function changeValue(obj){ ... } 中的 obj 被重新賦值的時候,外部變數的內容是不會被影響的。

1
2
3
4
5
6
7
8
9
10
11
var a= { value: 10 };


function changeValue(obj) {
obj = { value: 20 };

}

changeValue(a);

console.log(a); // 此時 a仍是 { value: 10 }

如果不是重新賦值的情況,則又會回到傳址的方式:

1
2
3
4
5
6
7
8
9
10
11
12
var a = { value: 10 };


function changeValue(obj) {
// 僅更新 obj.value,並未重新賦值
obj.value = 20;

}

changeValue(a);

console.log(a); // 此時 a 則會變成 { value: 20 }

參考文獻

  1. https://ithelp.ithome.com.tw/articles/10191057

  2. https://pjchender.blogspot.com/2016/03/javascriptby-referenceby-value.html