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