---
title: 'JS 核心 12 - 物件參考觀念的實際運作模式'
tags: JS 核心 ,JS , JavaScript, 物件參考
description: 2021/02/08
---
JS 核心 -- 物件參考觀念的實際運作模式
===
## 純值在傳遞是透過複製的方式
> 兩個變數擁有各自的值,兩者的值無任何關聯性
```
var person = '小明'; // 先宣告一個純值的變數
var person2 = person; // 宣告另一個變數,把'小明'的值賦予在此變數上
person2 = '杰倫';
console.log(person, person2); // 小明 杰倫
```

---
## 物件有傳參考的特性
### :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
```

### :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: "小明"}
```

> 這時沒有箭頭是指向同一個物件參考,目前物件都是獨立的
### :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: "大明"}
```

### :pencil2: **範例 4.** : 物件是傳參考的特性
要從 a 裡面找 y,又找回原本的參考物件,造成無限循環,不斷指向自己
y 屬性又指向 a 自己本身
```
var a = { x: 1 };
a.y = a; // 在 a 的物件下定義一個 y 屬性,並指向 a 物件
console.log(a);
```

### :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
```

### :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}}
```

<style>
.red {
color: red;
}
.green {
color: green;
}
</style>