理解属性描述对象
理解属性描述对象
1.概述
JavaScript提供了一个内部数据结构,用来描述一个对象的属性的行为,控制它的行为。这被称为“属性描述对象”(attributes object)。每个属性都有自己对应的属性描述对象,保存该属性的一些元信息。
实例:
{
value: 123,
writable: false,
enumerable: true,
configurable: false,
get: undefined,
set: undefined
}
属性描述对象提供6个元属性。
(1)value
value存放该属性的属性值,默认为undefined。
(2)writable
writable存放一个布尔值,表示属性值(value)是否可改变,默认为true。
(3)enumerable
enumerable存放一个布尔值,表示该属性是否可枚举,默认为true。如果设为false,会使得某些操作(比如for...in循环、Object.keys())跳过该属性。
(4)configurable
configurable存放一个布尔值,表示“可配置性”,默认为true。如果设为false,将阻止某些操作改写该属性,比如,无法删除该属性,也不得改变该属性的属性描述对象(value属性除外)。也就是说,configurable属性控制了属性描述对象的可写性。
(5)get
get存放一个函数,表示该属性的取值函数(getter),默认为undefined。
(6)set
set存放一个函数,表示该属性的存值函数(setter),默认为undefined。
ECMAScript中属性特性又分为两种属性:数据属性和访问器属性。
(1)数据属性
用来描述一个对象的属性的行为,控制它的行为
1.可枚举性(enumerable):
可枚举性(enumerable)用来控制所描述的属性,是否将被包括在for...in循环之中。 默认true
2.可配置性(configurable):
可配置性(configurable)决定了是否可以修改属性描述对象。 默认true
3.可写性(writable):
可写性(writable)决定了属性的值(value)是否可以被改变。 默认true,Value 包含这个属性的数据值 默认值为undefined
(2)访问器属性(该属性的值不是实际存在的,而是每次读取时计算生成的)
除了直接定义以外,属性还可以用存取器(accessor)定义。其中,存值函数称为setter,使用set命令;取值函数称为getter,使用get命令。
var o = {
get p() {
return 'getter';
},
set p(value) {
console.log('setter: ' + value);
}
};
o.p // "getter"
o.p = 123 // "setter: 123"
2.使用Object()自身静态方法对其操作
(1)使用Object.getOwnPropertyDescriptor()读出对象自身属性的属性描述对象
var o = { p: 'a' };
Object.getOwnPropertyDescriptor(o, 'p')
// Object { value: "a",
// writable: true,
// enumerable: true,
// configurable: true
// }
(2)使用Object.defineProperty(),Object.defineProperties()定义或改写属性,然后返回修改的对象
语法:Object.defineProperty(object, propertyName, attributesObject)
第一个是属性所在的对象,第二个是属性名(它应该是一个字符串),第三个是属性的描述对象。
var o = Object.defineProperty({}, 'p', {//定义一个属性
value: 123,
writable: false,
enumerable: true,
configurable: false
});
var o = Object.defineProperties({}, {//定义多个属性
p1: { value: 123, enumerable: true },
p2: { value: 'abc', enumerable: true },
p3: { get: function () { return this.p1 + this.p2 },
enumerable:true,
configurable:true
}
});
o.p1 // 123
o.p2 // "abc"
o.p3 // "123abc"
(3)使用Object.getOwnPropertyNames()方法返回直接定义在某个对象上面的全部属性的名称,不管该属性是否可枚举。
var o = Object.defineProperties({}, {
p1: { value: 1, enumerable: true },
p2: { value: 2, enumerable: false }
});
Object.getOwnPropertyNames(o)
// ["p1", "p2"]
(4)使用Object.prototype.propertyIsEnumerable()方法用来判断一个属性是否可枚举。
var o = {};
o.p = 123;
o.propertyIsEnumerable('p') // true
o.propertyIsEnumerable('toString') // false
用户自定义的p属性是可枚举的,而继承自原型对象的toString属性是不可枚举的。
下面是控制对象状态的一些方法
Object.preventExtensions():防止对象扩展。
Object.isExtensible():判断对象是否可扩展。
Object.seal():禁止对象配置。
Object.isSealed():判断一个对象是否可配置。
Object.freeze():冻结一个对象。
Object.isFrozen():判断一个对象是否被冻结。
链接:有关属性描述对象的更加详细内容看阮老师的属性描述对象一文。