ECMAScript中有兩種屬性:數據屬性和訪問器屬性
1. 數據屬性
數據屬性指包含一個數據值的位置,可在該位置讀取或寫入值,該屬性有4個供述其行爲的特性:
1. [[configurable]]:表示能否使用delete操作符刪除從而重新定義,或能否修改爲訪問器屬性。默認爲true;
2. [[Enumberable]]:表示是否可通過for-in循環返回屬性。默認true;
3. [[Writable]]:表示是否可修改屬性的值。默認true;
4. [[Value]]:包含該屬性的數據值。讀取/寫入都是該值。默認爲undefined;如上面實例對象Person中定義了name屬性,其值爲’wenzi’,對該值的修改都反正在這個位置
要修改對象屬性的默認特徵(默認都爲true),可調用Object.defineProperty()方法,它接收三個參數:屬性所在對象,屬性名和一個描述符對象,必須是:configurable、enumberable、writable和value,可設置一個或多個值
var person = {};
Object.defineProperty(
person, 'name', {
configurable: false, // 不可刪除,且不能修改爲訪問器屬性
writable: false, // 不可修改
value: 'wenzi' // name的值爲wenzi
}
);
console.log(person.name); // wenzi
console.log(delete person.name); // false,無法刪除
person.name = 'lily';
console.log(person.name); // wenzi
2. 訪問器屬性
訪問器屬性主要包括一對getter和setter函數,在讀取訪問器屬性時,會調用getter返回有效值;寫入訪問器屬性時,調用setter,寫入新值;該屬性有以下4個特徵:
1. [[Configurable]]:是否可通過delete操作符刪除重新定義屬性;
2. [[Numberable]]:是否可通過for-in循環查找該屬性;
3. [[Get]]:讀取屬性時自動調用,默認:undefined;
4. [[Set]]:寫入屬性時自動調用,默認:undefined;
要修改對象屬性的默認特徵(默認都爲true),可調用Object.defineProperty()方法,它接收三個參數:屬性所在對象,屬性名和一個描述符對象,必須是:configurable、enumberable、writable和value,可設置一個或多個值
訪問器屬性不能直接定義,必須使用defineProperty()來定義,如下:
var person = {
_age: 18
};
Object.defineProperty(person, 'isAdult', {
Configurable : false,
get: function () {
if (this._age >= 18) {
return true;
} else {
return false;
}
}
});
console.log( person.isAdult ); // true
Object.defineProperty()方法設置屬性時,不能同時聲明訪問器屬性(set和get)和數據屬性(writable或者value)。意思就是,某個屬性設置了writable或者value屬性,那麼這個屬性就不能聲明get和set了,反之亦然。
如若像下面的方式進行定義,訪問器屬性和數據屬性同時存在:
var o = {};
Object.defineProperty(o, 'name', {
value: 'wenzi',
set: function(name) {
myName = name;
},
get: function() {
return myName;
}
});
上面的代碼看起來貌似是沒有什麼問題,但是真正執行時會報錯,報錯如下:
Uncaught TypeError: Invalid property. A property cannot both have accessors and be writable or have a value
對於數據屬性,可以取得:configurable,enumberable,writable和value;
對於訪問器屬性,可以取得:configurable,enumberable,get和set。
3. 獲取Configurable值
ES5爲我們提供了Object.getOwnPropertyDescriptor(object, property)來獲取內部屬性
var person = {name:'wenzi'};
var desp = Object.getOwnPropertyDescriptor(person, 'name'); // person中的name屬性
console.log( desp );// {value: "wenzi", writable: true, enumerable: true, configurable: true}
console.log( person.name ); // wenzi
console.log( delete person.name ); // true,刪除成功
console.log( person.name ); // undefined
通過Object.getOwnPropertyDescriptor(object, property)我們能夠獲取到4個內部屬性,configurable控制着變量或屬性是否可被刪除。這個例子中,person.name的configurable是true,則說明是可以被刪除的.
4. 面試題
a = 1;
var desp = Object.getOwnPropertyDescriptor(window, 'a');
console.log( desp.configurable ); // true,可以刪除
var b = 2;
var desp = Object.getOwnPropertyDescriptor(window, 'b');
console.log( desp.configurable ); // false,不能刪除