---
# System prepended metadata

title: JS 核心 11 - 未定義的物件屬性、物件的參考特性
tags: [' 未定義的物件屬性', 'JS 核心 ', ' 物件的參考特性', 'JS ', ' JavaScript']

---

---
title: 'JS 核心 11 - 未定義的物件屬性、物件的參考特性' 
tags: JS 核心 ,JS , JavaScript, 未定義的物件屬性, 物件的參考特性
description: 2021/02/09
---

JS 核心 -- 未定義的物件屬性 與 物件的參考特性
===

## 未定義的物件屬性 
### 物件下未定義屬性，值為 undefined，在 undefined 上也無法再新增屬性

透過物件十字的方式建立物件
```typescript=
var family = {
  name: '小明家',  
}
console.log(family);   // {name: "小明家"}
```
> 若在物件下查找一個不存在的屬性，會回傳 undefined 的結果  

試著在 family 物件下查找一個不存在的屬性 ming
```typescript=5
console.log(family.ming); // undefined，無此值
```

> 無法新增任何屬性在 undefined 上  


```typescript=6
family.ming.name = '小明';  // 跳錯，無法對 undefined 的值新增 name 屬性
// Cannot set property 'name' of undefined (family.ming 不存在)
```

### :pencil: **解決方法 :**
1. **在建立物件十字時**，同時建立 ming 的屬性，就可把 name 屬性加上去。  
除了有 name 的屬性外，在 ming 裡面有正確加上 name 的屬性。
```
var family = {
  name: '小明家', 
  ming: {} 
}
family.ming.name = '小明';
console.log(family); 
```
![](https://i.imgur.com/qSS1xFF.png)

2. 若在一開始無法確定結構的情況下 : 直接**在物件下**新增屬性 (結果同上)   
```
var family = {
  name: '小明家', 
}
family.ming = {
  name: '小明', 
};
console.log(family); 
```

### 對全域物件下的屬性作檢查，要使用 window.a 查找

錯誤示範
```
var family = {
  name: '小明家', 
}
console.log(a);   // a is not defined，跳錯，程式碼中斷，後面不會執行
console.log(family); 
```
正確示範 : 未定義的物件屬性會回傳 undefined
```
var family = {
  name: '小明家', 
}
console.log(window.a);   // undefined ， 後面程式碼可以執行
console.log(family);     //  {name: "小明家"}
```

---

## 物件的參考特性
### JavaScript 賦予值在變數上時，有兩個特性 : 傳值、傳參考
![](https://i.imgur.com/XUjipq0.png)

### 變數為純值 : 透過傳值的方式做傳遞，<span class="red">沒有</span>傳參考的特性
* <span class="green">傳值是一種複製的概念</span>
    * 直接把 person 原本的值帶給 person2，person2 接收 ’小明’ 這個值
* <span class="green">傳值過去後，就和前者的值無關聯性</span>
    * person2 值怎麼修改就和前面無關聯性
    * 把 person2 改為 ’杰倫’，原本的 person 還是維持 ’小明’ 的狀態

```
var person = '小明';   // 先宣告一個純值的變數
var person2 = person;  // 宣告另一個變數，把'小明'的值賦予在此變數上
person2 = '杰倫';   
console.log(person, person2);  // 小明 杰倫
```
![](https://i.imgur.com/NGklZDb.png)


### 變數為物件 : 物件<span class="red">有</span>傳參考的特性
#### 改變物件內容時，前一個也會受到更動，即為物件傳參考特性
> 使用同一個參考路徑，只對應一個物件

```
var person = {
  name: '小明',
  money: 1000
}
var person2 = person;
```
1. 定義 person 等於一個物件的時候，執行結果如下圖
2. 定義 person，後面帶入的是記憶體的參考路徑 (並不是帶入完整的物件內容)
3. 當參考路徑指向物件時，可取得裡面的 name、money 內容
4. person 不會把 name、money 的值存到記憶體空間，只會傳入一個參考

![](https://i.imgur.com/py7aJfL.png)

把 person2.name 改為'杰倫';  
```
person2.name = '杰倫';
console.log(person, person2);     // {name: "杰倫"} {name: "杰倫"}
console.log(person === person2);  // true
```

5. 把 person2 裡的 name 改為 ’杰倫’，因為都使用同一個參考物件
   ( person 和 person2 裡的 name 同時受到修改)
6. 只有產生一個參考路徑，一個參考路徑對應一個物件 ( person 和 person2 共用同一個物件) 

![](https://i.imgur.com/ZVp0mH8.png)


:pencil2: **範例 : 傳參考 (若指向另一個物件，就會產生另一個參考位置)**   
> 當宣告一個物件時，就等於在記憶體空間上準備了新的參考位置  
> 不同的參考位置就算屬性和值相同，但兩者比對還是 false  

1. 一開始定義 person 物件，person 物件指向 0x01 這個參考位置
2. 又定義 person2 物件指向前一個 person 物件，兩者共用 0x01 這個參考位置 (如左圖)
```
var person = {
  name: '小明',
  money: 1000
}
var person2 = person;
```
試著將 person2 指向新物件
```
person2 = {      // 指向新的物件，就會產生新的參考位置
  name: '小明',
}   
console.log(person, person2);     // {name: "小明"} {name: "小明"}
console.log(person === person2);  // false，person 和 person2 無關聯性
```
3. 當指向另一個物件時，就會產生新的參考位置 (如右圖)
4. person 和 person2 無關聯性。 就算 person2 修改 name 內容，person 也不會改變。
![](https://i.imgur.com/kfP6cYe.png)




## :memo: 學習回顧  
:::info
* 物件下的未定義屬性，值為 undefined，在 undefined 上也無法再新增屬性
* 對全域物件下的屬性作檢查，要使用 window.a 查找
* JavaScript 賦予值在變數上時，有兩個特性 : 傳值、傳參考
    * 純值透過<span class="red">傳值</span>的方式做傳遞 (沒有傳參考的特性)
    * 物件有<span class="red">傳參考</span>的特性
* 當宣告一個物件時，就等於在記憶體空間上準備了新的參考位置
    * 不同的參考位置就算屬性和值相同，但兩者比對還是 false
:::

## :+1: 相關參考文件 
:::info
[JavaScript 物件的連連看!? 兩個物件的值居然會一樣](https://wcc723.github.io/javascript/2017/12/10/javascript-reference/)  
:::

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