JavaScript 核心觀念(27)-物件-物件參考觀念的實際運作模式

前言

前一章節講的物件傳參考觀念,其實在說明上還是很模糊,所以這一章節來實際了解運作模式吧。

純值的運作

首先先來看一下簡單的範例

1
2
3
4
5
var a = 'Ray';

var b = {
name: 'Ray',
};

在上面範例中細分為兩個部分,一個是純值一個是物件,接下來我們來畫一張圖,分別代表物件與純值

在一開始 JavaScript 會先準備好兩個變數,並且先指向到 undefined (提升的觀念,所以沒有什麼太大問題)

指向 undefined

接下來因為 JavaScript 會準備一個記憶體空間放置我們的純值,此時 a 會指向該記憶體空間,而這個記憶體空間可能是 0x01,因此 a 其實是取得 0x01 的記憶體空間並且賦予回去而已

記憶體空間

接下來我們會有一個行為是 var c = a;a 複製到 c,這邊要注意純值在賦予到其他變數時,是指向同一個記憶體空間並賦予值(複製一份過來)而已

1
2
3
var a = 'Ray';

var c = a;

指向同一個記憶體空間

我相信這邊已經非常混亂了,所以我用動畫呈現了一下

動畫呈現

因此你在修改 c 的值時,並不會影響到 a,因為他是重新指向到另一個記憶體空間叫做 0x02

1
2
3
4
5
var a = 'Ray';

var c = a;

c = '123';

新的記憶體空間

這也是為什麼我們修改 c 時並不會影響到 a,因為兩者是不同的記憶體空間。

物件傳參考

接下來講講比較難的東西,也就是物件,在物件中基本上我們看到變數後面接著 { } 就可以知道是一個物件

1
2
3
var b = {
name: 'Ray',
};

並且我們也知道物件有一個東西叫做「物件傳參考」,顧名思義我們賦予到另一個變數之後病修改裡面的屬性,原有的屬性會被修改

1
2
3
4
5
6
7
8
var b = {
name: 'Ray',
};

var e = b;

e.name = 'QQ';
console.log(b.name); // QQ

那這一段在記憶體空間與指向上又是怎樣呢?首先 { } 一樣會建立一個記憶體空間(undefined 那一段我就不提了)假設是 0x03 並且指向賦予回來

物件記憶體指向

這一段基本上應該沒什麼問題,與純值那邊很像

但是重點是在於屬性的部分,目前屬性是一個純值概念,這些屬性都有屬於自己的記憶體空間,而 name 是只存活在這個 0x03 的記憶體空間底下的屬性,這個屬性也會指向另一個記憶體空間例如 0x04,這邊概念與純值得很像

屬性記憶體指向

我相信這邊指向概念已經很混亂了,所以也補上動畫圖

記憶體指向動畫

那麼接下來講講為什麼當我們使用 var e = b; 並且修改 name 屬性時,原有的物件會被修改,首先我們一樣會建立一個變數 e 這時候記憶體空間會指向到 b 的記憶體位置,這一段應該沒什麼太大問題

變數 e 記憶體指向到變數 b 的記憶體空間

接下來重點來了,我們可以看到上方圖片我們的記憶體空間一直是指著 0x03,因此我們在操作 e.name 時,其實是操作 0x03 底下 name 屬性指向的 0x04 記憶體空間,這也就是為什麼 e.name = 'Ray' 會影響到原有的 b 物件,因為從頭到尾都是相同的指向記憶體。

1
2
3
4
5
6
7
8
var b = {
name: 'Ray',
};

var e = b;

e.name = 'QQ';
console.log(b.name); // QQ

因此如果你希望建立一個新的物件空間時,請重新宣告一個物件或者賦予一個物件,這樣才不會導致物件傳參考的事情發生,因此記憶體空間都不同了。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
var b = {
name: 'Ray',
};

var e = b;

e = {
name: 'Ray',
};

e.name = 'QQ';

console.log(b.name); // QQ 先生
console.log(e.name); // QQ

最後我也補一下記憶體指向的圖片與動畫

重新賦予一個物件

底下是動畫版的記憶體指向

新物件記憶體指向

參考文獻