---
title: 'JS 核心 26 - 物件擴充的修改與調整'
tags: JS 核心 ,JS , JavaScript, object
description: 2021/02/06
---
JS 核心 26 - 物件屬性不可寫入?物件擴充的修改與調整
===
### 延伸的三個物件方法 : 直接針對物件本身做調整,可以對巢狀屬性做調整
* preventExtensions : 防止擴充 (使用此方法,物件的屬性特徵<span class="red">**不會**</span>被改變) - 無法新增屬性
* 驗證是否被擴充 Object.isExtensible(person)
* seal : 封裝 (使用此方法,物件的屬性特徵<span class="red">**會**</span>被改變)
* 驗證是否被封裝 Object.isSealed(person)
* Freeze : 凍結 (使用此方法,物件的屬性特徵<span class="red">**會**</span>被改變)
* 驗證是否被凍結 Object.isFrozen(person)
> <span class="red">使用 Object.getOwnPropertyDescriptor(person, 'a') 來查看物件的屬性特徵</span>
## 「防止擴充」方法 : Object.preventExtensions(物件本身)
### 「防止擴充」的用意就是無法新增屬性。
> 「防止擴充」無法對他的巢狀屬性做限制
```
var person = {
a: 1, // 純值
b: 2, // 純值
c: {} // 純物件
}
console.log('是否可被擴充', Object.isExtensible(person)); // true (驗證是否可被擴充)
```
若加上防止擴充語法 : Object.preventExtensions(物件本身)
> 不是調整物件的屬性 ; 是直接對物件來做限制
```typescript=
var person = {
a: 1, // 純值
b: 2, // 純值
c: {} // 純物件
}
Object.preventExtensions(person); // 防止擴充
console.log('是否可被擴充', Object.isExtensible(person)); // false (驗證是否可被擴充)
console.log('person a 的屬性特徵', Object.getOwnPropertyDescriptor(person, 'a'));
```
(承上程式碼) 試著調整 person 物件裡的屬性特徵如下
```typescript=9
person.a = 'a'; // 調整屬性
person.d = 'd'; // 新增屬性 (因為 person 物件設定「防止擴充」,因此無法新增屬性)
person.c.a = 'ca'; // 巢狀屬性調整,可以在 c 屬性下新增屬性 a
Object.defineProperty(person, 'a', { // 調整特徵
configurable: false // 屬性 a 無法被刪除
});
delete person.b; // 刪除屬性 b
// 結果
console.log('person 物件', person); // (如下圖) (其中 person.b 被刪除了)
console.log('person a 屬性特徵(嘗試修改後)', Object.getOwnPropertyDescriptor(person, 'a'));
```

### ☞ 總結 : 「防止擴充」用意就是無法新增屬性,其他屬性特徵可以調整。
## 「封裝」方法 : Object.seal(物件本身)
### 「封裝」方法 : 讓物件屬性無法新增刪除,也無法重新配置特徵,但是可以調整目前屬性值。 writable 為 true。
### 「封裝」方法預設狀態 : 物件會被加上 「防止擴充」preventExtensions 的條件
```typescript=
var person = {
a: 1, // 純值
b: 2, // 純值
c: {} // 純物件
}
Object.seal(person);
// false (物件狀態有包含「防止擴充」preventExtensions)
console.log('是否可被 擴充', Object.isExtensible(person));
console.log('是否可被 封裝', Object.isSealed(person)); // true
console.log('person a 的屬性特徵', Object.getOwnPropertyDescriptor(person, 'a'));
```

(承上程式碼) 試著調整 person 物件裡的屬性特徵如下
```typescript=10
person.a = 'a'; // 調整屬性
// 新增屬性 (無法新增屬性)(物件狀態預設包含「防止擴充」preventExtensions)
person.d = 'd';
person.c.a = 'ca'; // 巢狀屬性調整
Object.defineProperty(person, 'a', { // 調整特徵 (使用封裝 seal ,無法更改屬性特徵)
writable: false
});
delete person.b; // 刪除 (使用封裝 seal ,屬性無法被刪除)
console.log('person 物件', person);
console.log('a 屬性特徵(嘗試修改後)', Object.getOwnPropertyDescriptor(person, 'a'));
```

## 「凍結」方法 : Object.freeze(物件本身)
### 「凍結」方法 : 物件會加上 seal 特性,且無法調整值。 writable 為 false。
```typescript=
var person = {
a: 1, // 純值
b: 2, // 純值
c: {} // 純物件
}
Object.freeze(person);
console.log('是否可被擴充', Object.isExtensible(person));// false(物件狀態包含 "seal" 特性)
console.log('是否可被封裝', Object.isSealed(person)); // true (物件狀態包含 "seal" 特性)
console.log('是否被凍結', Object.isFrozen(person)); // true
console.log('person a 的屬性特徵', Object.getOwnPropertyDescriptor(person, 'a')); //(如下圖)
```

(承上程式碼) 試著調整 person 物件裡的屬性特徵如下
```typescript=11
person.a = 'a'; // 調整屬性 (使用凍結 freeze ,無法更改值)
person.d = 'd'; // 新增屬性 (無法新增屬性)(物件狀態預設包含「防止擴充」preventExtensions)
person.c.a = 'ca'; // 巢狀屬性調整 (物件有參考的特性,只能對 "當下的物件屬性" 做凍結或封裝)
```
嘗試調整被凍結的物件屬性特徵,會跳錯 (物件狀態有包含 "seal" 特性,無法重新定義他的屬性特徵)
```typescript=14
Object.defineProperty(person, 'a', {
configurable: true
});
```
(第 14-16 行註解掉)
```typescript=17
delete person.b; // 刪除 (物件狀態有包含 "seal" 特性 ,屬性無法被刪除)
console.log('person 物件', person);
console.log('person a 屬性特徵(嘗試修改後)', Object.getOwnPropertyDescriptor(person, 'a'));
```

## :memo: 學習回顧
:::info
* Object.defineProperty 方法是針對物件裡的屬性特徵來做操作。
* 三個延伸方法是直接針對物件本身做操作,整個物件必須使用額外方法來驗證他 (可以對巢狀屬性做調整)
* 是否被擴充 Object.isExtensible(物件本身)
* 是否被封裝 Object.isSealed(物件本身)
* 是否被凍結 Object.isFrozen(物件本身)
* 使用 Object.getOwnPropertyDescriptor(person, ‘a’) 來查看物件的屬性特徵
* 三個物件延伸的方法
* Object.preventExtensions(物件本身) : 防止擴充 (使用此方法,物件的屬性特徵不會被改變)
* Object.seal(物件本身) : 封裝 (使用此方法,物件的屬性特徵會被改變)
* Object.freeze(物件本身) : 凍結 (使用此方法,物件的屬性特徵會被改變)
1. 「防止擴充」用意就是無法新增屬性,其他屬性特徵可以調整。
2. 「封裝」 : 讓物件屬性無法新增刪除,也無法重新配置特徵,但是可以調整目前屬性值。 writable 為 true。
* 「封裝」方法預設狀態 : 物件會被加上「防止擴充」preventExtensions 的特性
3. 「凍結」方法 : 物件會加上 seal 特性,且無法調整值。 writable 為 false。
* 「凍結」方法預設狀態 : 物件會被加上「封裝」seal 的特性
:::
## :+1: 相關參考文件
:::info
:::
<style>
.red {
color: red;
}
.green {
color: green;
}
</style>