{ PH_Dev }

Published on

傳值(By value)與傳參考(By reference)

Authors
  • avatar
    Name
    Penghua Chen(PH)
    Twitter

傳值(By value)與傳參考(By reference)

講在前面: 這個篇幅會搭配 understanding the weird parts(克服JS奇怪的部分) 的影片章節來學習。

而篇幅會聚焦在 by value(傳值)、 by reference (傳參考)這兩個方向, by sharing 則留待日後更加了解後再學習、比較。

影片中有兩張關鍵圖片,這裡會以此作為起點並向下延伸。

call by value (傳值)

Day10-1

從圖中可以知道:

若某個變數值為基本型別值(primitive value),當指定給另一個變數時,==該變數會建立一個新的記憶體位址,並拷貝這個基本型別的值儲存到新的記憶體位址上。==

來看看一個測試的例子:

var a = 5;
var b;
b = a;
console.log('a的值為: ' + a);
console.log('b的值為: ' + b);

Day10-1

到這邊應該還不難理解,再來我們在測試看看另一個例子:

var a = 5;
var b;
b = a;
a = 6;
console.log('a的值為: ' + a);
console.log('b的值為: ' + b);

跟前一個例子很類似,只是多了一行程式 ==改變 a 的值==,這時候再來看看兩個變數的值會是怎麼樣

Day-11-3

可以知道,即使我們修改了 a 的值, b 也不會因此而被修改。

因為將 a 的值傳給 b ,實際上是只有單純的把 a 的值 5 拷貝一份,然後儲存到 b 的記憶體裡。

而上述就是剛剛講在前面的 ==call by value(傳值)==

再來讓我們往下看看 call by reference (傳參考)

call by reference (傳參考)

Day11-4

從圖中可以知道:

==若某個變數的值為物件時==,當把該變數的值傳給另一個變數時,此時==這兩個變數會指向同一個記憶體位址==。也因此如果修改了物件中的特性與方法,自然就會同時變更到另一個物件。

來看看這個測試例子:

var obj = {
  greeting: 'Hello'
  };
var obj2;
obj2 = obj;
console.log(obj);
console.log(obj2);

從圖中的結果可以得知當透過 obj2 = obj ,兩者指向同一個記憶體位址,並非是兩個不同的記憶體位址。

再來看看變更了其中一個物件的特性值,看會是什麼情況。

Day11-5

var obj = {
  greeting: 'Hello'
  };
var obj2;
obj2 = obj;
console.log(obj);
console.log(obj2);
obj2.greeting = 'Hola';
console.log(obj);
console.log(obj2);

obj2 中的特性 greeting 值修改為 Hola ,可以看到 obj 物件竟然也同時被修改了 greeting 特性的值。

原因就是因為兩者都指向同一個記憶體位址的緣故,所以才會改了其中一個,而另一個也被修改了。

而上述就是剛剛講在前面的 ==call by reference(傳參考)==

Day11-6

但凡事總是有所謂的例外情況:

例外情況

前面有提到,所有的物件都是 call by reference,

但當如果有下列這種情況時,就不是 call by reference :

var obj = {
  greeting: 'Hello'
  };
var obj2;
obj2 = obj;
obj = {
  greeting: 'Hi'
};
console.log(obj);
console.log(obj2);

obj 透過物件字面值的方式建立了一個新的物件,所以此時的 objobj2 已經是指向兩個不同記憶體位址的物件。

自然也就不會因為更改 objobj2 也跟著被更改。

Day11-7

關於 傳值(By value)與傳參考(By reference) 的學習就先到這囉