講在前面: 這個篇幅會搭配 understanding the weird parts(克服JS奇怪的部分) 的影片章節來學習。
而篇幅會聚焦在 by value(傳值)、 by reference (傳參考)這兩個方向, by sharing 則留待日後更加了解後再學習、比較。
影片中有兩張關鍵圖片,這裡會以此作為起點並向下延伸。
從圖中可以知道:
若某個變數值為基本型別值(primitive value),當指定給另一個變數時 該變數會建立一個新的記憶體位址,並拷貝這個基本型別的值儲存到新的記憶體位址上。
來看看一個測試的例子:
var a = 5;
var b;
b = a;
console.log('a的值為: ' + a);
console.log('b的值為: ' + b);
到這邊應該還不難理解,再來我們在測試看看另一個例子:
var a = 5;
var b;
b = a;
a = 6;
console.log('a的值為: ' + a);
console.log('b的值為: ' + b);
跟前一個例子很類似,只是多了一行程式 改變 a
的值,這時候再來看看兩個變數的值會是怎麼樣
可以知道,即使我們修改了 a
的值, b
也不會因此而被修改。
因為將 a
的值傳給 b
,實際上是只有單純的把 a
的值 5
拷貝一份,然後儲存到 b
的記憶體裡。
而上述就是剛剛講在前面的 call by value(傳值)
再來讓我們往下看看 call by reference (傳參考)
從圖中可以知道:
若某個變數的值為物件時,當把該變數的值傳給另一個變數時,此時這兩個變數會指向同一個記憶體位址。也因此如果修改了物件中的特性與方法,自然就會同時變更到另一個物件。
來看看這個測試例子:
var obj = {
greeting: 'Hello'
};
var obj2;
obj2 = obj;
console.log(obj);
console.log(obj2);
從圖中的結果可以得知當透過 obj2 = obj
,兩者指向同一個記憶體位址,並非是兩個不同的記憶體位址。
再來看看變更了其中一個物件的特性值,看會是什麼情況。
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(傳參考)
但凡事總是有所謂的例外情況:
前面有提到,所有的物件都是 call by reference,
但當如果有下列這種情況時,就不是 call by reference :
var obj = {
greeting: 'Hello'
};
var obj2;
obj2 = obj;
obj = {
greeting: 'Hi'
};
console.log(obj);
console.log(obj2);
obj
透過物件字面值的方式建立了一個新的物件,所以此時的 obj
、obj2
已經是指向兩個不同記憶體位址的物件。
自然也就不會因為更改 obj
而 obj2
也跟著被更改。
關於 傳值(By value)與傳參考(By reference) 的學習就先到這囉
明天見~