屬性描述符(Property Descriptors)
var myObject = {
a: 2
};
Object.getOwnPropertyDescriptor( myObject, "a" );
// {
// value: 2,
// writable: true,
// enumerable: true,
// configurable: true
// }
我們普通的對象屬性a的屬性描述符(稱為“數(shù)據(jù)描述符”,因為它僅持有一個數(shù)據(jù)值)的內容要比value為2多得多。它還包含另外3個性質:writable糜工,enumerable捕传,和configurable筐骇。
可寫性(Writable)
writable控制著你改變屬性值的能力债鸡。
var myObject = {};
Object.defineProperty( myObject, "a", {
value: 2,
writable: false, // 不可寫!
configurable: true,
enumerable: true
} );
myObject.a = 3;
myObject.a; // 2
我們對value的修改悄無聲息地失敗了
可配置性(Configurable)
只要屬性當前是可配置的铛纬,我們就可以使用同樣的defineProperty(..)工具厌均,修改它的描述符定義。
var myObject = {
a: 2
};
myObject.a = 3;
myObject.a; // 3
Object.defineProperty( myObject, "a", {
value: 4,
writable: true,
configurable: false, // 不可配置告唆!
enumerable: true
} );
myObject.a; // 4
myObject.a = 5;
myObject.a; // 5
Object.defineProperty( myObject, "a", {
value: 6,
writable: true,
configurable: true,
enumerable: true
} ); // TypeError
最后的defineProperty(..)調用導致了一個TypeError棺弊,這與strict mode無關,如果你試圖改變一個不可配置屬性的描述符定義擒悬,就會發(fā)生TypeError模她。要小心:如你所看到的,將configurable設置為false是 一個單向操作茄螃,不可撤銷缝驳!
注意: 這里有一個需要注意的微小例外:即便屬性已經(jīng)是configurable:false,writable總是可以沒有錯誤地從true改變?yōu)閒alse归苍,但如果已經(jīng)是false的話不能變回true用狱。
configurable:false阻止的另外一個事情是使用delete操作符移除既存屬性的能力。
對象常量(Object Constant)
通過將writable:false與configurable:false組合拼弃,你可以實質上創(chuàng)建了一個作為對象屬性的 常量(不能被改變夏伊,重定義或刪除),比如:
var myObject = {};
Object.defineProperty( myObject, "FAVORITE_NUMBER", {
value: 42,
writable: false,
configurable: false
} );
防止擴展(Prevent Extensions)
如果你想防止一個對象被添加新的屬性吻氧,但另一方面保留其他既存的對象屬性溺忧,調用Object.preventExtensions(..):
var myObject = {
a: 2
};
Object.preventExtensions( myObject );
myObject.b = 3;
myObject.b; // undefined
封印(Seal)和 凍結(Freeze)
Object.seal(..)創(chuàng)建一個“封印”的對象盯孙,這意味著它實質上在當前的對象上調用Object.preventExtensions(..)鲁森,同時也將它所有的既存屬性標記為configurable:false。
所以振惰,你既不能添加更多的屬性歌溉,也不能重新配置或刪除既存屬性(雖然你依然 可以 修改它們的值)。
Object.freeze(..)創(chuàng)建一個凍結的對象骑晶,這意味著它實質上在當前的對象上調用Object.seal(..)痛垛,同時也將它所有的“數(shù)據(jù)訪問”屬性設置為writable:false,所以他們的值不可改變桶蛔。
存在性(Existence)
in和hasOwnPrototype
in操作符會檢查屬性是否存在于對象中匙头,或者是否存在于[[Prototype]]鏈對象遍歷的更高層中。
相比之下仔雷,hasOwnProperty(..) 僅僅 檢查myObject是否擁有屬性蹂析,但不會查詢[[Prototype]]鏈
var myObject = {
a: 2
};
("a" in myObject); // true
("b" in myObject); // false
myObject.hasOwnProperty( "a" ); // true
myObject.hasOwnProperty( "b" ); // false
枚舉(Enumeration)
var myObject = { };
Object.defineProperty(
myObject,
"a",
// 使`a`可枚舉,如一般情況
{ enumerable: true, value: 2 }
);
Object.defineProperty(
myObject,
"b",
// 使`b`不可枚舉
{ enumerable: false, value: 3 }
);
myObject.b; // 3
("b" in myObject); // true
myObject.hasOwnProperty( "b" ); // true
// .......
for (var k in myObject) {
console.log( k, myObject[k] );
}
你會注意到碟婆,myObject.b實際上 存在电抚,而且擁有可以訪問的值,但是它不出現(xiàn)在for..in循環(huán)中(然而令人詫異的是脑融,它的in操作符的存在性檢查通過了)喻频。這是因為“enumerable”基本上意味著“如果對象的屬性被迭代時會被包含在內”。
Object.keys()和Object.getOwnPropertyNames() 肘迎、propertyIsEnumerable
1.Object.keys()返回一個所有可枚舉屬性的數(shù)組甥温,而Object.getOwnPropertyNames()返回一個 所有 屬性的數(shù)組,不論能不能枚舉妓布。
2.propertyIsEnumerable()測試一個給定的屬性名是否直 接存 在于對象上姻蚓,并且是enumerable:true。
var myObject = { };
Object.defineProperty(
myObject,
"a",
// 使`a`可枚舉匣沼,如一般情況
{ enumerable: true, value: 2 }
);
Object.defineProperty(
myObject,
"b",
// 使`b`不可枚舉
{ enumerable: false, value: 3 }
);
myObject.propertyIsEnumerable( "a" ); // true
myObject.propertyIsEnumerable( "b" ); // false
Object.keys( myObject ); // ["a"]
Object.getOwnPropertyNames( myObject ); // ["a", "b"]
in和hasOwnProperty(..)區(qū)別于它們是否查詢[[Prototype]]鏈狰挡,而Object.keys(..)和Object.getOwnPropertyNames(..)都 只 考察直接給定的對象。