JS之preventExtensions、seal和freeze

深藍一人發表於2018-01-09

preventExtensions

預設情況下,所有物件都是可擴充套件的。在呼叫preventExtensions之後,將不能再往物件中新增屬性(嚴格模式報錯,非嚴格模式靜默失敗),對已有屬性沒有影響

let obj1 = {name: 'xiaohua'};
Object.preventExtensions(obj1);
obj1.name = 'xiaomei';
obj1.name //xiaomei 已有屬性可讀可寫
obj1.age=23
obj1.age // undefined,新增屬性靜默失敗
複製程式碼

seal

密封屬性;密封屬性不可擴充套件;而且已有成員的configurable屬性會被設定為false

let obj2 = {name: 'xiaohua'};
Object.seal(obj2);
Object.isExtensible(obj2) // false, 不可擴充套件
obj1.age=23
obj1.age // undefined,新增屬性靜默失敗
Object.getOwnPropertyDescriptor(obj2, 'name') //  writable: true, enumerable: true, configurable: false
複製程式碼

freeze

凍結物件;凍結物件不可擴充套件且密封;而且已有成員的configurable及writable屬性會被設定為false

let obj3 = {name: 'xiaohua'};
Object.freeze(obj3)
Object.isExtensible(obj3) // false, 不可擴充套件
Object.isSealed(obj3) // true, 密封
Object.getOwnPropertyDescriptor(obj2, 'name') //  writable: false, enumerable: true, configurable: false
複製程式碼

補充知識

兩種定義物件屬性的方式比較

使用obj = {age: 2}定義物件的屬性,其writable,enumerable,configurable均為true

let obj = {age: 2};
Object.getOwnPropertyDescriptor(obj, 'age');
// value: 2, writable: true, enumerable: true, configurable: true
複製程式碼

Object.defineProperty(obj, prop, descriptor),使用defineProperty定義物件的屬性,其中未定義的屬性預設為false

let obj2 = {};
Object.defineProperty(obj2, 'age', {value: 2});
Object.getOwnPropertyDescriptor(obj2, 'age');
// value: 2, writable: false, enumerable: false, configurable: false
Object.defineProperty(obj2, 'favourites', {value: 'js', writable: true});
Object.getOwnPropertyDescriptor(obj2, 'favourites');
// value: "js", writable: true, enumerable: false, configurable: false
複製程式碼

writable,enumerable,configurable

物件的資料屬性

writable:表示能否修改屬性的值。true時,可以重寫該屬性的值;屬性為false時,修改屬性的值在非嚴格模式下不會生效,嚴格模式下會報錯。

enumerable:表示能否通過for-inObject.keys()迴圈返回屬性。true時可以訪問,false不可以訪問到

configurable:表示能否通過delete刪除屬性,能否通過Object.defineProperty()修改屬性的特性。值為true時可以delete並且可以修改,值為false時,表示不能從物件中刪除屬性。如果對這個屬性呼叫delete,則在非嚴格模式下什麼也不會,但是嚴格模式下會導致錯誤。而且,此時,再呼叫Object.defineProperty()方法修改除writable之外的特性,都會導致錯誤。

let person = {};
Object.defineProperty(person, 'name', {value: 'xiaohua', writable: true, enumerable: true});
// writable: true, enumerable: true, configurable: false
Object.defineProperty(person, 'name', { enumerable: false}); // 報錯
Object.defineProperty(person, 'name', { writable: false}); // configurable為false, 且writable為true時,可以修改writable
// writable: false, enumerable: true, configurable: false
Object.defineProperty(person, 'name', { writable: true}); // 報錯
複製程式碼

value:表示這個屬性的資料值,預設為undefined

在呼叫Object.defineProperty()方法時,以上屬性預設 false

訪問器屬性

訪問器屬性不包含資料值-它們是一對getter和setter函式。訪問器屬性有如下4個特性

configurable: 同上

enumerable: 同上

get:在讀取屬性時呼叫的函式

set:在寫入屬性時呼叫的函式

相關文章