Object. defineProperty()用于在一个对象上添加或者修改属性,并返回这个对象。
Object. defineProperty(obj, prop, descriptor)
参数
- obj: 目标对象,要在上面添加或修改属性的对象
- prop:要定义或修改的属性
- descriptor:属性描述符
通过赋值操作添加的属性是可以枚举的,可以使用for-in、Object.keys呈现出来,并且值是可以被修改和删除。Object. defineProperty()方法允许修改对象的默认配置,该方法在默认情况下定义的属性是不可枚举的。
描述符
描述符分为:数据描述符、存取描述符(描述符必须是下面之一,但不能同时存在)
- 数据描述符:是一个具有值的属性,该值可能是可变的,可能是不变的。
- 存取描述符:具有getter-setter函数对描述的属性。
数据描述符、存取描述符同时具有以下可选属性:
- configurable: 为true时,该属性描述符才能被修改,同时该属性才能被删除, 默认false。
- enumerable: 为true时,该属性才可枚举,默认false。
数据描述符具有以下可选属性:
- value: 属性的值,默认undefined。
- writable:为true时,属性的value值才能被赋值运算符改变,默认false。
存取描述符具有以下可选属性:
- get:如果没有getter则为undefined。
- set: 如果没有setter则为undefined。
如果一个属性不具有writable、value、get、set中的任何一个,会被认为是一个数据描述符。如果同时存在(writable或value)和(get或set)关键字,将会产生异常
创建属性
同时上面的属性,不仅仅时对象自身的属性,也包括继承的属性,所以为了确保这些默认值,你可以使用Object.create(null)将__proto__指向null,或者Object.freeze(obj.protptype);
var obj = {};
var descriptor = Object.create(null);
descriptor.value = 'foo';
Object.defineProperty(obj, 'key', descriptor);
修改属性
如果Object.defineProperty()设置configurable为false,那么该属性被认为“不可配置”,并且没有属性可以被修改(除了单方面的将writbale改为false)。
- writable
为false时该属性不可再分配。
var foo = {};
Object.defineProperty(o, 'a', {
value: 'bar',
writable: false
});
foo.a = 'baz'; // 严格模式会抛出任何错误
- enumerable
定义了对象的属性是否可以被枚举,for-in、Object.keys()
var obj = {};
Object.defineProperty(obj, 'a', {
enumerable: true,
value: 1
})
Object.defineProperty(obj, 'b', {
enumerable: false,
value: 2
})
console.log(Object.keys(obj)) //["a"]
- configurable
表示属性是否可以被删除,以及初writable之外的数据是否可以被修改。
var obj = {};
Object.defineProperty(obj, 'a', {
configurable: false,
value: 1
})
Object.defineProperty(obj, 'a', { configurable: true }); //Uncaught TypeError: Cannot redefine property: a
Object.defineProperty(obj, 'a', { enumerable: true }); //Uncaught TypeError: Cannot redefine property: a
Object.defineProperty(obj, 'a', { writable: true }); //Uncaught TypeError: Cannot redefine property: a
Object.defineProperty(obj, 'a', { set: function() {} }); //Uncaught TypeError: Cannot redefine property: a
使用点运算符和Object.defineProperty()时的默认值如下:
var obj = {};
//点运算符
obj.a = '1';
//如同
Object.defineProperty(obj, 'a', {
configurable: true,
writable: true,
enumerable: true,
value: '1'
});
// Object.defineProperty();
Object.defineProperty(obj, 'a', {
value: '1'
});
//如同
Object.defineProperty(obj, 'a', {
configurable: false,
writable: false,
enumerable: false,
value: '1'
});