JavaScript对象的property属性详解及其Object.defineProperty方法
JavaScript中对象的property有三个属性:
1.writable。该property是否可写。
2.enumerable。当使用for/in语句时,该property是否会被枚举。
3.configurable。该property的属性是否可以修改,property是否可以删除。
在ECMAScript 3标准中,上面三个属性的值均为true且不可改:新建对象的property是可写的、可被枚举的、可删除的;而在ECMAScript 5标准中,可通过property的描述对象(property descriptor)来对这些属性进行配置和修改。
如果将property的值信息也作为property的属性来看的话,对象中的property拥有四个属性:value、writable、enumerable和configurable。
ECMAScript5.1(ECMA-262)中定义了标准属性Object.defineProperty 方法
ECMAScript 5标准中,可以通过Object.getOwnPropertyDescriptor()来获取对象自身某个property的属性信息:
1 var o = {x:1}; 2 var a = Object.create(o); 3 a.y = 3; 4 console.log(Object.getOwnPropertyDescriptor(a, "y"));//Object {configurable=true, enumerable=true, writable=true, value=3} 5 console.log(Object.getOwnPropertyDescriptor(a, "x"));//undefined
可以看到,如果property不存在或者property继承自原型对象,则返回undefined。
ECMAScript 5标准中,可以通过Object.defineProperty()来设置对象自身某个property的属性:
Object.defineProperty(obj, prop, descriptor)
obj,待修改的对象prop,带修改的属性名称descriptor,待修改属性的相关描述
descriptor 要求传入一个对象,其默认值如下,
/**
* @{param} descriptor
*/
{
configurable: false,
enumerable: false,
writable: false,
value: null,
set: undefined,
get: undefined
}
configurable,属性是否可配置。可配置的含义包括:是否可以删除属性(delete),是否可以修改属性的writable、enumerable、configurable属性。enumerable,属性是否可枚举。可枚举的含义包括:是否可以通过for...in遍历到,是否可以通过Object.keys()方法获取属性名称。writable,属性是否可重写。可重写的含义包括:是否可以对属性进行重新赋值。value,属性的默认值。set,属性的重写器(暂且这么叫)。一旦属性被重新赋值,此方法被自动调用。get,属性的读取器(暂且这么叫)。一旦属性被访问读取,此方法被自动调用。
经过上述的示例,正常情况下 Object.definePropert() 的使用都是比较简单的。
不过还是有一点需要额外注意一下, Object.defineProperty() 方法设置属性时,属性不能同时声明访问器属性( set 和 get )和 writable 或者 value 属性。 意思就是,某个属性设置了 writable 或者 value 属性,那么这个属性就不能声明 get 和 set 了,反之亦然。
因为 Object.defineProperty() 在声明一个属性时,不允许同一个属性出现两种以上存取访问控制。
示例代码,
var o = {},
myName = 'erik';
Object.defineProperty(o, 'name', {
value: myName,
set: function(name) {
myName = name;
},
get: function() {
return myName;
}
});
上面的代码看起来貌似是没有什么问题,但是真正执行时会报错,报错如下,
TypeError: Invalid property. A property cannot both have accessors and be writable or have a value, #<Object>
因为这里的 name 属性同时声明了 value 特性和 set 及 get 特性,这两者提供了两种对 name 属性的读写控制。这里如果不声明 value 特性,而是声明writable 特性,结果也是一样的,同样会报错。


浙公网安备 33010602011771号