---
# System prepended metadata

title: JS 核心 12 - 物件參考觀念的實際運作模式
tags: ['JS 核心 ', 'JS ', ' JavaScript', ' 物件參考']

---

---
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>