var person = {
name: "Nicholas",
age: 29,
job: "Software Engineer",
sayName: function(){
alert(this.name);
}};
這個特性默認值為true。9?[[Value]]:包含這個屬性的數據值。讀取屬性值的時候,從這個位置讀;寫入屬性值的時候,
把新值保存在這個位置。這個特性的默認值為undefined。
對于像前面例子中那樣直接在對象上定義的屬性,它們的[[Configurable]]、[[Enumerable]]
和[[Writable]]特性都被設置為true,而[[Value]]特性被設置為指定的值。例如:10
1.數據屬性
數據屬性包含一個數據值的位置。在這個位置可以讀取和寫入值。數據屬性有4個描述其行為的特性。
?[[Configurable]]:表示能否通過delete刪除屬性從而重新定義屬性,能否修改屬性的特
性,或者能否把屬性修改為訪問器屬性。像前面例子中那樣直接在對象上定義的屬性,它們的這個特性默認值為true。
?[[Enumerable]]:表示能否通過for-in循環返回屬性。像前面例子中那樣直接在對象上定
義的屬性,它們的這個特性默認值為true。
?[[Writable]]:表示能否修改屬性的值。像前面例子中那樣直接在對象上定義的屬性,它們的這個特性默認值為true。
?[[Value]]:包含這個屬性的數據值。讀取屬性值的時候,從這個位置讀;寫入屬性值的時候,
把新值保存在這個位置。這個特性的默認值為undefined。
對于像前面例子中那樣直接在對象上定義的屬性,它們的[[Configurable]]、[[Enumerable]]
和[[Writable]]特性都被設置為true,而[[Value]]特性被設置為指定的值。例如:
var person = {
name: "Nicholas"
};
這里創建了一個名為name的屬性,為它指定的值是"Nicholas"。也就是說,[[Value]]特性將被設置為"Nicholas",而對這個值的任何修改都將反映在這個位置。
Object.defineProperty()
var person = {};
Object.defineProperty(person, "name", {
writable: false,
value: "Nicholas"
});
alert(person.name); //"Nicholas"
person.name = "Greg";
alert(person.name); //"Nicholas"
這個例子創建了一個名為name的屬性,它的值"Nicholas"是只讀的。這個屬性的值是不可修改的,如果嘗試為它指定新值,則在非嚴格模式下,賦值操作將被忽略;在嚴格模式下,賦值操作將會導致拋出錯誤。
類似的規則也適用于不可配置的屬性。例如:
var person = {};
Object.defineProperty(person, "name", {
configurable: false,
value: "Nicholas"
});
alert(person.name); //"Nicholas"
delete person.name;
alert(person.name); //"Nicholas"
把configurable設置為false,表示不能從對象中刪除屬性。如果對這個屬性調用delete,則在非嚴格模式下什么也不會發生,而在嚴格模式下會導致錯誤。而且,一旦把屬性定義為不可配置的,就不能再把它變回可配置了。此時,再調用Object.defineProperty()方法修改除writable之外的特性,都會導致錯誤:
var person = {};
Object.defineProperty(person, "name", {
configurable: false,
value: "Nicholas"
});
//拋出錯誤
Object.defineProperty(person, "name", {
configurable: true,
value: "Nicholas"
});
也就是說,可以多次調用Object.defineProperty()方法修改同一個屬性,但在把configurable特性設置為false之后就會有限制了。
在調用Object.defineProperty()方法時,如果不指定,configurable、enumerable和writable特性的默認值都是false。多數情況下,可能都沒有必要利用Object.defineProperty()方法提供的這些高級功能。不過,理解這些概念對理解JavaScript對象卻非常有用。
2.訪問器屬性
訪問器屬性不包含數據值;它們包含一對兒getter和setter函數(不過,這兩個函數都不是必需的)。
?[[Configurable]]:表示能否通過delete刪除屬性從而重新定義屬性,能否修改屬性的特
性,或者能否把屬性修改為數據屬性。對于直接在對象上定義的屬性,這個特性的默認值為true。
[[Enumerable]]:表示能否通過for-in循環返回屬性。對于直接在對象上定義的屬性,這5個特性的默認值為true。
?[[Get]]:在讀取屬性時調用的函數。默認值為undefined。
?[[Set]]:在寫入屬性時調用的函數。默認值為undefined。
訪問器屬性不能直接定義,必須使用Object.defineProperty()來定義。請看下面的例子。
以上代碼創建了一個book對象,并給它定義兩個默認的屬性:_year和edition。_year前面
的下劃線是一種常用的記號,用于表示只能通過對象方法訪問的屬性。而訪問器屬性year則包含一個getter函數和一個setter函數。getter函數返回_year的值,setter函數通過計算來確定正確的版本。因此,把year屬性修改為2005會導致_year變成2005,而edition變為2。這是使用訪問器屬性的常見方式,即設置一個屬性的值會導致其他屬性發生變化。
不一定非要同時指定getter和setter。只指定getter意味著屬性是不能寫,嘗試寫入屬性會被忽略。在嚴格模式下,嘗試寫入只指定了getter函數的屬性會拋出錯誤。類似地,只指定setter函數的屬性也不能讀,否則在非嚴格模式下會返回undefined,而在嚴格模式下會拋出錯誤。
定義多個屬性
由于為對象定義多個屬性的可能性很大,ECMAScript 5又定義了一個Object.definePro-
perties()方法。利用這個方法可以通過描述符一次定義多個屬性。這個方法接收兩個對象參數:第一個對象是要添加和修改其屬性的對象,第二個對象的屬性與第一個對象中要添加或修改的屬性一一對應。例如:
讀取屬性的特性
使用ECMAScript 5的Object.getOwnPropertyDescriptor()方法,可以取得給定屬性的描述
符。這個方法接收兩個參數:屬性所在的對象和要讀取其描述符的屬性名稱。返回值是一個對象,如果是訪問器屬性,這個對象的屬性有configurable、enumerable、get和set;如果是數據屬性,這個對象的屬性有configurable、enumerable、writable和value。