1. 简介
Object.defineProperty() 静态方法会直接在一个对象上定义一个新属性,或修改其现有属性,并返回此对象。
2. 用法
Object.defineProperty(obj, prop, descriptor)
- obj: 要操作的对象
- prop: 要定义或修改的属性键
- descriptor: 要定义或修改的属性的描述符
- value: 属性的值
- writable:属性的值是否可写 如果是true,则可以被重写,否则就是只读
- configurable: 是否可配置
- enumerable:是否可枚举
- get: 当获取该属性值时触发get方法,返回值为该属性值
- set:当设置该属性值时触发set方法,参数为设置的属性值。
描述符中[value, writable]和[get, set]不能同时出现。
value = 1;
Object.defineProperty(obj, 'test', {
get(){
return value * 2;
},
set(newVal){
value = value * 2;
}
})
obj.test // 2
obj.test = 2
obj.test // 4
3. obj.key = value
obj1 = {a: 1};
obj1.b = 2;
console.log(obj1); // {a: 1, b: 2}
obj2 = {a: 1};
Object.defineProperty(obj2, 'b', {value: 2});
console.log(obj2); // {a: 1, b: 2}
以上两种方式有什么异同?
通过
Object.getOwnPropertyDescriptors可以看到,在writable enumerable configurable这三个描述符的属性上,
- Object.key方式赋值,以上三个属性默认为
true - defineProperty方式默认为
false
4. writable
当 writable 特性设置为 false 时,该属性不可写,不能被重新赋值。
尝试对一个不可写的属性进行写入不会改变它,在严格模式下会导致错误。
obj = {}
Object.defineProperty(obj, 'a', {
value: 1,
writable: false,
configurable: true,
enumerable: true
})
obj.a = 2
console.log(obj) // {a: 1}
可以看到,对属性a赋值无效
5. configurable
configurable 特性控制属性是否可以从对象中删除以及其特性(除了 value 和 writable)是否可以更改。
- 不影响
value和writable - 可支持 writable 修改一次,从
true改为false - writable为
false时,value也无法修改了
Object.defineProperty(obj, "key", {
value: 1,
writable: true,
configurable: false, // 不可配置
enumerable: true,
});
修改描述符,会报错
Object.defineProperty(obj, 'key', {
value: 2,
writable: false,
configurable: false,
enumerable: false
})
// Uncaught TypeError: Cannot redefine property: key
// at Function.defineProperty (<anonymous>)
可以修改writable为false,但无法再修改为true
Object.defineProperty(obj, 'key', {
writable: false,
}) // 成功
6. enumerable
设置该属性是否可枚举
obj = {test : 1};
Object.defineProperty(obj, 'key', {
value: 2,
writable: true,
configurable: true,
enumerable: false // 设置enumerable为false, 则该属性就不可以被枚举了
})
console.log(obj); // {test: 1, key: 2}
- Object.keys()
Object.keys(obj) // ['test']
- for...in
for(item in obj){
console.log(item);
}
// test
7. getter / setter
value 与 getter / setter 不可同时出现。
value = 1;
Object.defineProperty(obj, 'test', {
get(){
return value * 2;
},
set(newVal){
value = value * 2;
}
})
obj.test // 2
obj.test = 2
obj.test // 4
- 第一次调用getter,返回
1 * 2的结果,为 2 - 第一次调用setter,更新value值,为
1 * 2= 2 - 第二次调用getter,返回
2 * 2的结果,为 4