--- title: 'JS 核心 12 - 物件參考觀念的實際運作模式' tags: JS 核心 ,JS , JavaScript, 物件參考 description: 2021/02/08 --- JS 核心 -- 物件參考觀念的實際運作模式 === ## 純值在傳遞是透過複製的方式 > 兩個變數擁有各自的值,兩者的值無任何關聯性 ``` var person = '小明'; // 先宣告一個純值的變數 var person2 = person; // 宣告另一個變數,把'小明'的值賦予在此變數上 person2 = '杰倫'; console.log(person, person2); // 小明 杰倫 ``` ![](https://i.imgur.com/PHZNnfu.png) --- ## 物件有傳參考的特性 ### :pencil2: **範例 1.** : 共用同一個參考位置 ``` var person = { // 產生記憶體空間 0x01 name: '小明' // 定義屬性和值 } var person2 = person; // person2 和 person 共用同一個參考位置 (如左圖) ``` 當要修改 person2 裡的 name 時,尋找 person2 的記憶體位置 0x01 裡的 name 修改成 ‘杰倫’ (如右圖) ``` person2.name = '杰倫'; console.log(person, person2); // {name: "杰倫"} {name: "杰倫"} console.log(person === person2); // true ``` ![](https://i.imgur.com/arGHBwG.png) ### :pencil2: **範例 2.** : 指向新物件會產生新的記憶體空間,創立新的參考物件 ```typescript= var family = { // 定義一個 family 物件 name: '小明家', // 屬性 name 為純值 members: { // 屬性 members 為物件 father: '老爸', mom: '老媽', ming: '小明' }, }; var member = family.members; // 目前和 family.members 的參考位置相同為 0x02 (如左圖) ``` member 指向新物件會產生新的記憶體空間,創立新的參考物件。 member 和 family.members 已無關聯性。 (如右圖) ```typescript=10 member = { // member 又指向新物件 (創立新的參考物件) ming: '大明' // 此時 member 物件和 family.members 無關聯性 } console.log(member, family.members); // {ming: "大明"} {father: "老爸", mom: "老媽", ming: "小明"} ``` ![](https://i.imgur.com/wKLkGwR.png) > 這時沒有箭頭是指向同一個物件參考,目前物件都是獨立的 ### :pencil2: **範例 3.** : 若是直接修改屬性,並沒有重新指向物件,則參考位置還是一樣的。 因為 members 和 member 都指向同一個參考位置 0x02,ming 的屬性值同時被修改 ``` var family = { // 定義一個 family 物件 name: '小明家', // 屬性 name 為純值 members: { // 屬性 members 為物件 father: '老爸', mom: '老媽', ming: '小明' }, }; var member = family.members; member.ming = '大明'; // 直接找到 0x02 的參考位置,把 ming 屬性值改為 '大明' console.log(member, family.members); // {father: "老爸", mom: "老媽", ming: "大明"} {father: "老爸", mom: "老媽", ming: "大明"} ``` ![](https://i.imgur.com/Qjae94Y.png) ### :pencil2: **範例 4.** : 物件是傳參考的特性 要從 a 裡面找 y,又找回原本的參考物件,造成無限循環,不斷指向自己 y 屬性又指向 a 自己本身 ``` var a = { x: 1 }; a.y = a; // 在 a 的物件下定義一個 y 屬性,並指向 a 物件 console.log(a); ``` ![](https://i.imgur.com/yhqk4zk.png) ### :pencil2: **範例 5.** : 物件和傳參考的關係 ```typescript= var a = { x: 1 }; // 參考路徑為 0x01 var b = a; // 把 b 指向 a 物件,把 a 的參考路徑 0x01 帶入 (如左圖) ``` > <span class="red">同時賦值是同時執行,運算子的相依性依然存在。</span> > 順序上會是從右至左賦值,同時執行程式碼。 "等於" 為運算子,是一個運算式,會接收回傳值 (如中圖) * a = { x: 2 } 是一個運算式,執行結果為 { x: 2 } * { x: 2 } 的結果會賦予到 a 和 a.y 上 * a.y = a = { x: 2 } 這一行是同時執行的,執行 a.y 時不會因為 a = { x: 2 } 的執行而改變。 * a 參考路徑變成 0x02 * a.y (是新增屬性值) 不會找到 a 新的參考路徑 0x02 → 找的是原本的參考路徑 0x01 ```typescript=3 a.y = a = { x: 2 }; // 定義新物件 { x: 2 }、參考路徑為 0x02,賦予到 a.y 和 a 上 console.log(a); // {x: 2},指向參考位置 0x02 console.log(a.y); // undefined (目前的 a 參考位置是 0x02 ,無 a.y 的屬性值) console.log(b); // (如右圖) console.log(a === b.y); // true,兩者的參考位置都指向 0x02 ``` ![](https://i.imgur.com/Vp2CLWg.png) ### :pencil2: **練習** 依據執行的步驟拆分頁面,說明以下程式碼的執行結果 a 首先指向 0x01 位置 ,b 也指向 0x01 位置 (如圖一) ``` var a = { x: 1}; // 新增 0x01 的參考位置 var b = a; ``` a 新增了 x 屬性,值是一個新的物件,所以新增一個 0x02 參考位置 (如圖二) ``` a.x = { x: 2}; // 新增 0x02 的參考位置 ``` a.y = a = { y: 1}; 這段是同時執行的 (如圖三) * a={y:1} 使得 a 指向新的位置 → 0x03 * a.y={y:1},這裡的 a 會依照原本的路徑 0x01 去新增屬 性,所以在 0x01 新增 y-0x03 ``` a.y = a = { y: 1}; console.log(a); // {y: 1} console.log(b); // {x:{x:2},y:{y:1}} ``` ![](https://i.imgur.com/QdbcOtI.png) <style> .red { color: red; } .green { color: green; } </style>