Object.defineProperty方法
Object.defineProperty方法
定义
Object.defineProperty() 方法会直接在一个对象上定义一个新属性,或者修改一个对象的现有属性,并返回此对象。
语法
Object.definePrototype(obj,prop,descriptor)
- obj:要定义属性的对象。
- prop:要定义或修改的属性的名称。
- descriptor:要定义或修改的属性描述符。
返回值:被传递给函数的对象。
描述
此方法允许精确地添加或修改对象的属性。通过赋值操作添加的普通属性是可枚举的,可以改变这些属性值,也可以删除这些属性值。默认情况下使用此方法添加的属性值是不可修改的。
对象里目前存在的属性描述符有两种主要形式:
数据描述符
是一个具有值的属性,该值可以是可写的,也可以是不可写的。
configurable:
是否可以重新定义,当且仅当该属性键值为true时,该属性的描述符才能够被改变,同时该属性也能从对应的对象上被删除。默认为false。
enumerable:
是否可以枚举,当且仅当该属性键值为true时,该属性才会出现在对象的枚举属性中。默认为false。
value:
该属性对应的值。默认为undefined。
writable:
是否可以修改属性值,当且仅当该属性的键值为true时,上面的value才能被赋值运算符改变,默认为false。
存取描述符
由getter函数和setter函数所描述的属性还可以具有以下可选键。
get :
属性的getter函数,如果没有getter,则为undefined。动态计算得到当前属性值 (回调函数)。默认为undefined,当访问该属性时,会调用此函数。
set :
监视当前属性值的变化,更新其他相关的属性(回调函数)。当属性值被修改时,会调用此函数。默认为undefined。
注意
一个描述符只能是这两者其中之一,不能同时是两者。
这两种描述符都是对象,描述符可拥有的键值:
如果一个描述符不具有value、writable 、get、set中任意一个键,那么它将被认为是一个数据描述符。如果一个描述符同时拥有value或writable和get或set键则会出现异常。
| configurable | enumerable | value | writable | get | set | |
|---|---|---|---|---|---|---|
| 数据描述符 | 可以 | 可以 | 可以 | 可以 | 不可以 | 不可以 |
| 存取描述符 | 可以 | 可以 | 不可以 | 不可以 | 可以 | 可以 |
代码演示
创建属性
// 创建属性
var o = {};
Object.defineProperty(o,"a",{
value:37,
writable:true,
enumerable:true,
configurable:true
});
//对象o拥有了属性a,值为37
//在对象中添加一个设置了存取描述符属性的示例
var Bvalue = 38;
Object.defineProperty(o,"b",{
get(){
return Bvalue;
},
set(newValue){
Bvalue = newValue;
},
enumerable:true,
configurable:true
});
console.log(o.a);修改属性writable
当writable属性设置为false时,该属性被称为“不可写的”。
var o = {};//创建一个对象
Object.defineProperty(o,'a',{
value:37,
writable:false,
})
console.log(o.a);
o.a = 25;
console.log(o.a);Enumerable 属性
定义了对象的属性是否可以在 for…in 循环和 Object.keys() 中被枚举。
var o = {};
Object.defineProperty(o,"a",{value:1,enumerable:true});
Object.defineProperty(o,"b",{value:2,enumerable:false});
Object.defineProperty(o,"c",{value:3});
o.d = 4;
Object.defineProperty(o,Symbol.for('e'),{
value:5,
enumerable:true
});
for(var i in o){
console.log(i);
}
console.log(Object.keys(o));运行结果:

configurable 特性
表示对象的属性是否可以被删除,以及除 value 和 writable 特性外的其他特性是否可以被修改。
var o = {};
Object.defineProperty(o,"a",{
get(){return 1},
configurable:false,
});
Object.defineProperty(o,"a",{
configurable:true,
});
Object.defineProperty(o,"a",{
enumerable:true,
});
Object.defineProperty(o,"a",{
set(){}
});
Object.defineProperty(o,"a",{
get(){return 1},
configurable:false,
});
Object.defineProperty(o,"a",{
value:12
});
console.log(o.a);
delete o.a;
console.log(o.a);运行结果:会在第14行报错。

设置getter()和setter()
function Archiver() {
var temperature = null;
var archive = [];
Object.defineProperty(this,'temperature',{
get:function(){
console.log('get!');
return temperature;
},
set:function(value){
temperature = value;
archive.push({val:temperature});
}
});
this.getArchive = function(){return archive};
}
var arc = new Archiver();
arc.temperature;
arc.temperature = 11;
arc.temperature = 13;
console.log(arc.getArchive());运行结果:

<body>
<script type="text/javascript" >
let number = 18
let person = {
name:'张三',
sex:'男',
}
Object.defineProperty(person,'age',{
// value:18,
// enumerable:true, //控制属性是否可以枚举,默认值是false
// writable:true, //控制属性是否可以被修改,默认值是false
// configurable:true //控制属性是否可以被删除,默认值是false
//当有人读取person的age属性时,get函数(getter)就会被调用,且返回值就是age的值
get(){
console.log('有人读取age属性了')
return number
},
//当有人修改person的age属性时,set函数(setter)就会被调用,且会收到修改的具体值
set(value){
console.log('有人修改了age属性,且值是',value)
number = value
}
})
// console.log(Object.keys(person))
console.log(person)
</script>
</body>