​Object.defineProperty()​​方法允许通过属性描述对象,定义或修改一个属性,然后返回修改后的对象,它的用法如下。

Object.defineProperty(object, propertyName, attributesObject)

Object.defineProperty方法接受三个参数,依次如下。

  • ​object​​:属性所在的对象
  • ​propertyName​​:字符串,表示属性名
  • ​attributesObject​​:属性描述对象

例如:

var obj = Object.defineProperty({}, 'p', {
value: 123,
writable: false,
enumerable: true,
configurable: false
});

obj.p // 123

obj.p = 246;
obj.p // 123

上面代码中,​​Object.defineProperty()​​​方法定义了​​obj.p​​​属性。由于属性描述对象的​​writable​​​属性为​​false​​​,所以​​obj.p​​​属性不可写。注意,这里的​​Object.defineProperty​​​方法的第一个参数是​​{}​​​(一个新建的空对象),​​p​​​属性直接定义在这个空对象上面,然后返回这个对象,这是​​Object.defineProperty()​​​的常见用法。
如果属性已经存在,​​​Object.defineProperty()​​​方法相当于更新该属性的属性描述对象。
如果一次性定义或修改多个属性,可以使用​​​Object.defineProperties()​​方法。

var obj = Object.defineProperties({}, {
p1: { value: 123, enumerable: true },
p2: { value: 'abc', enumerable: true },
p3: { get: function () { return this.p1 + this.p2 },
enumerable:true,
configurable:true
}
});

obj.p1 // 123
obj.p2 // "abc"
obj.p3 // "123abc"

上面代码中,​​Object.defineProperties()​​​同时定义了​​obj​​​对象的三个属性。其中,​​p3​​​属性定义了取值函数​​get​​,即每次读取该属性,都会调用这个取值函数。

【注意】:一旦定义了取值函数​​get​​​(或存值函数​​set​​​),就不能将​​writable​​​属性设为​​true​​​,或者同时定义​​value​​属性,否则会报错。

var obj = {};

Object.defineProperty(obj, 'p', {
value: 123,
get: function() { return 456; }
});
// TypeError: Invalid property.
// A property cannot both have accessors and be writable or have a value

Object.defineProperty(obj, 'p', {
writable: true,
get: function() { return 456; }
});
// TypeError: Invalid property descriptor.
// Cannot both specify accessors and a value or writable attribute

上面代码中,同时定义了​​get​​​属性和​​value​​​属性,以及将​​writable​​​属性设为​​true​​,就会报错。

​Object.defineProperty()​​​和​​Object.defineProperties()​​​参数里面的属性描述对象,​​writable​​​、​​configurable​​​、​​enumerable​​​这三个属性的默认值都为​​false​​。

var obj = {};
Object.defineProperty(obj, 'foo', {});
Object.getOwnPropertyDescriptor(obj, 'foo')
// {
// value: undefined,
// writable: false,
// enumerable: false,
// configurable: false
// }