前言
在先前有介紹到如果要調整屬性的特徵我們可以使用 Object.defineProperty 與 Object.defineProperties 這兩個物件的方法。那麼接下來我們要來介紹如何讓物件可以防止物件擴張、封裝物件與凍結物件的方法,這些方法分別為:
- Object.preventExtensions() 防止物件擴張
- Object.seal() 封裝物件
- Object.freeze() 凍結物件
Object.preventExtensions()
Object.preventExtensions() 的作用為防止擴充,透過下方的程式碼範例可以了解,對物件使用 preventExtensions 的時候,依舊可以調整屬性值,也可以修改屬性特徵,能夠刪除屬性,不過無法新增新的屬性。
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'));
|

Object.seal()
使用 Object.seal() 可以讓物件屬性無法新增刪除(巢狀屬性可以被調整),也無法重新配置特徵,但是可以調整目前屬性值。(該物件會被加上 preventExtensions)
var person = { a: 1, b: 2, c: {} }
Object.seal(person); console.log('是否可被 封裝', Object.isSealed(person)); console.log('person a 的屬性特徵', Object.getOwnPropertyDescriptor(person, 'a'));
person.a = 'a';
person.d = 'd';
person.c.a = 'ca';
Object.defineProperty(person, 'a', { writable: false });
delete person.b;
console.log('person 物件', person); console.log('person a 屬性特徵(嘗試修改後)', Object.getOwnPropertyDescriptor(person, 'a'));
|

雖然說 Object.seal() 無法重新配置屬性特徵,不過在 MDN 的文件中有提到 writable 的屬性特徵可以調整為 false。

所以如果我們在使用 Object.seal() 的情況下嘗試修改物件中其他的屬性特徵,就會出現以下的錯誤訊息。
Object.defineProperty(person, 'a', { enumerable: false });
|

Object.freeze()
再針對物件使用 Object.freeze() 的時候,無法新增、修改予刪除屬性值(巢狀屬性可以修改),無法修物件的屬性特徵。
var person = { a: 1, b: 2, c: {} }
Object.freeze(person); console.log('是否被凍結', Object.isFrozen(person)); console.log('person a 的屬性特徵', Object.getOwnPropertyDescriptor(person, 'a'));
person.a = 'a';
person.d = 'd';
person.c.a = 'ca';
delete person.b;
console.log('person 物件', person); console.log('person a 屬性特徵(嘗試修改後)', Object.getOwnPropertyDescriptor(person, 'a'));
|

在物件設定 Object.freeze() 的情況下調整屬性特徵,會跳出錯誤訊息並終止程式碼運行:
Object.defineProperty(person, 'a', { configurable: true });
|

章節結論
- 使用 Object.preventExtensions() 可以防止物件擴張,無法新增物件屬性。
- 使用 Object.seal() 會封裝物件,使物件無法新增與刪除物件屬性(巢狀屬性可調整屬性值),不過可以調整屬性值;無法調整屬性特徵,除了 writable 可設定為 false 不再此限制。
- 使用 Object.freeze() 會凍結物件,使物件無法新增、刪除、調整屬性值(巢狀屬性可調整屬性值),也無法調整屬性特徵。
參考文件