JavaScript 核心觀念(28)-物件-物件參考之章節作業

前言

接下來這章節是物件參考的章節作業,這章節主要是確保物件傳參考的觀念有正確的吸收。

章節範例程式碼

下面這邊是章節作業的範例程式碼,必須以記憶體指向的方式來拆分執行結果。

1
2
3
4
5
6
var a = { x: 1};
var b = a;
a.x = { x: 2};
a.y = a = { y: 1};
console.log(a); // 結果?
console.log(b); // 結果?

第一階段

首先我們在一開始會宣告變數 ab,而在一開始會有所謂的提升,並且一開始提升會預設指向到 undefined 這個記憶體位置

提升

這時候你可能會說 abundefined 指向的記憶體位置都是相同的?其實沒錯,這邊我們可以輸入以下程式碼來驗證

1
2
3
var a; // undefined
var b; // undefined
console.log(a === b); true

這邊也附上動畫繪畫

動畫效果

第二步驟

接下來是執行階段的記憶體賦予,因此這邊同時物件會建立一個記憶體位置,並且 a 的記憶體位置會被賦予到 b

1
2
a = { x: 1};
b = a;

記憶體建立與賦予

在這邊的過程如果不清楚的話,可以回顧我上一章節。

動畫運作

第三階段

在這邊接下來的行為會稍微複雜一點,其中因為針對 a.x 賦予到另一個新的物件記憶體空間,並且額外新增了一個屬性叫做 a.y 並在最後同時執行了 a.y = a = { y: 1}; 的新的記憶體空間,但是在這邊說同時執行可能會很混亂,因此可以用相依性特性來看,等號的相依性是從右邊開始,因此 a = { y: 1}; 會優先執行,並且會因為表達式會回傳結果,所以 a.y 其實是接收表達式的結果,因此你可以看成以下

1
2
3
a.x = { x: 2};
a.y = { y: 1}; // 注意這一行與下面那一行是同時執行
a = { y: 1};

接下來就讓我們看圖解吧

物件賦予到新物件

相信這邊記憶體指向很混亂了,所以一樣來看動圖會比較好懂

記憶體指向

上面動圖要注意 a.y = a = { y: 1}; 是同時執行,只是因為繪畫上只能一個一個順序執行

因此結尾的 console.log 答案是以下

1
2
3
4
5
6
7
var a = { x: 1};
var b = a;
a.x = { x: 2};
a.y = a = { y: 1};

console.log(a); // { y: 1}
console.log(b); // {x: { x: 2}, y: { y: 1}}

在這邊記憶體指向是相對比較複雜,但是透過圖解,可以注意到 b 從頭到尾都指向著一開始的記憶體位置,而我們所有操作都是針對原有的 0x01 記憶體去操作,只是後來 a 被賦予到新的記憶體位置,但是基於物件是傳參考,使用記憶體指向,所以 b 才會持續指向原有的記憶體位置。

這一章節相對比較複雜,因此會比較需要多次複雜前面的章節觀念。

參考文獻