物件擴充的修改與調整
這個章節一共會教三個物件方法:
- preventExtensions - 防止擴充
- seal - 封裝
- Freeze - 凍結
preventExtensions - 防止擴充
preventExtensions
用意是無法新增屬性。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30
| var person = { a: 1, b: 2, c: {} }
Object.preventExtensions(person); console.log('是否可被擴充', Object.isExtensible(person)); console.log('person a 的屬性特徵', Object.getOwnPropertyDescriptor(person, 'a'));
// 調整屬性 person.a = 'a';
// 新增屬性 person.d = 'd'; // 無效,因為防止擴充無法新增屬性
// 巢狀屬性調整 person.c.a = 'ca'; // 有效,因為防止擴充只能限制第一層
// 調整特徵 Object.defineProperty(person, 'a', { configurable: false });
// 刪除 delete person.b;
// 結果 console.log('person 物件', person); console.log('person a 屬性特徵(嘗試修改後)', Object.getOwnPropertyDescriptor(person, 'a'));
|
我們可以看到 preventExtensions
主要的功能就是防止擴充,但是它的作用只能在指定物件的第一層屬性。因為物件是傳址的,所以只能對當下的屬性作動。
所以我們去刪除屬性、調整屬性都是被允許的。
seal - 封裝
seal
: 讓指定物件的屬性無法新增、刪除,也無法重新配置特徵,但是可以調整屬性值。
- 預設會讓物件加上
preventExtensions
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31
| var person = { a: 1, b: 2, c: {} }
Object.seal(person); console.log('是否可被擴充', Object.isExtensible(person)); console.log('是否被 封裝 ', Object.isSealed(person)); console.log('person a 的屬性特徵', Object.getOwnPropertyDescriptor(person, 'a'));
// 調整屬性 person.a = 'a'; // 有效,seal可以調整屬性值
// 新增屬性 person.d = 'd'; // 無效,seal 無法新增、刪除屬性
// 巢狀屬性調整 person.c.a = 'ca'; // 有效,因為 seal 只能限制第一層
// 調整特徵 Object.defineProperty(person, 'a', { writable: false // 無效,seal 無法重新配置特徵 });
// 刪除 delete person.b; // 無效, seal 無法新增、刪除屬性
// 結果 console.log('person 物件', person); console.log('person a 屬性特徵(嘗試修改後)', Object.getOwnPropertyDescriptor(person, 'a'));
|
可以看到seal
不能被新增、刪除屬性,也無法重新配置特徵,但是可以被調整屬性值。
seal
跟 preventExtensions
一樣只能限制到第一層的屬性。主要是因為物件是傳址的,所以只能對當下的屬性作動。
freeze
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27
| var person = { a: 1, b: 2, c: {} }
Object.freeze(person); console.log('是否可被擴充', Object.isExtensible(person)); console.log('是否被 封裝 ', Object.isSealed(person)); console.log('是否被 凍結 ', Object.isFrozen(person)); console.log('person a 的屬性特徵', Object.getOwnPropertyDescriptor(person, 'a'));
// 調整屬性 person.a = 'a'; // 無效, freeze 無法調整值
// 新增屬性 person.d = 'd'; // 無效,freeze 無法新增、刪除屬性
// 巢狀屬性調整 person.c.a = 'ca'; // 有效,因為 freeze 只能限制第一層
// 刪除 delete person.b; // 無效, freeze 無法新增、刪除屬性
// 結果 console.log('person 物件', person); console.log('person a 屬性特徵(嘗試修改後)', Object.getOwnPropertyDescriptor(person, 'a'));
|
freeze
有 seal
的所有功能,但是它又多了一個不能調整值的功能。
還有另外一點,它在調整屬性特徵時 console.log
會跳錯。