该属性能够定义一个对象的新属性,或者修改一个对象已有的属性值,返回这个被处理过的对象
参数:
obj:要操作的对象
prop:obj上要定义或修改的属性
descriptor:属性描述器,用于定义或修改该属性的特性。该属性描述器分为两类:数据描述符和存取描述符。
数据描述符:一个具有值的属性,该值可能是可写的,也可能不是可写的。
存取描述符:由getter-setter函数对描述的属性。
描述符必须是这两种形式之一;不能同时是两者。
属性描述器descriptor的key共有6种,分别为:
特别注意以下三点:
0.记住,这些选项不一定是自身属性,如果是继承来的也要考虑。为了确认保留这些默认值,你可能要在这之前冻结 Object.prototype,明确指定所有的选项,或者通过 Object.create(null)将proto属性指向null。
1.configurable、enumerable既是数据描述符,又是存取描述符
2.value、writable与get、set只能存在其一,同时存在报错。
3.如果对象可枚举,则使用for…in或Object.keys()可以遍历
value:属性对应的值,可以是任意类型的值,默认为undefined
let obj = Object.create(null);
Object.defineProperty(obj, 'name', {
value:'zhuangzhuang'
})
console.log(obj);//{"name":"zhuangzhuang"}
writable:属性的值是否能够被重新赋值,true为可以重新赋值,false为不可以重新赋值,默认为false
注意:writable为false,但是实际去重新赋值了,不报错,值也不改变
let obj = Object.create(null);
Object.defineProperty(obj, 'name', {
value:'zhuangzhuang',
writable:true
})
obj.name = 'yuhua';
console.log(obj);//{"name":"yuhua"}
Object.defineProperty(obj, 'name', {
writable:false
})
obj.name = 'zhuangzhuang';
console.log(obj);//{"name":"yuhua"}
当设置或获取对象的某个属性的值的时候,可以提供getter/setter方法。
getter 是一种获得属性值的方法。当我们去读取属性的值时,调用getter方法。
setter是一种设置属性值的方法。当我们去设定或修改属性值时,调用setter。
let obj = Object.create(null);
let initVal = 'zhuangzhuang';
Object.defineProperty(obj, 'name', {
get:function(){
return initVal;
},
set:function(setVal){//参数为设置的值
initVal = setVal;
}
})
console.log(obj.name);//'zhuangzhuang'
obj.name = 'yuhua';
console.log(obj.name);//'yuhua'
赋值一个初始值’zhuangzhuang’给initVal,当走第一个console.log时,会执行get函数,也就是返回initVal,为’zhuangzhuang’;当走obj.name=’yuhua’时,会执行set函数,将赋的值’yuhua’通过set函数参数传入,给initVal,这时候initVal变成了’yuhua’;然后走第二个console.log时,会走get函数,读取最新的initVal为’yuhua’。
enumerable:此属性是否可以被枚举(使用for…in或Object.keys())。设置为true可以被枚举;设置为false,不能被枚举。默认为false。
var obj = {}
//第一种情况:enumerable设置为false,不能被枚举。
Object.defineProperty(obj,"newKey",{
value:"hello",
writable:false,
enumerable:false
});
//枚举对象的属性
for( var attr in obj ){
console.log( attr );
}
//第二种情况:enumerable设置为true,可以被枚举。
Object.defineProperty(obj,"newKey",{
value:"hello",
writable:false,
enumerable:true
});
//枚举对象的属性
for( var attr in obj ){
console.log( attr ); //newKey
}
configurable:是否可以删除目标属性或是否可以再次修改属性的特性(writable, configurable, enumerable)。设置为true可以被删除或可以重新设置特性;设置为false,不能被可以被删除或不可以重新设置特性。默认为false。
这里分为两点——是否可以删除目标属性、是否可以在此修改属性的特性(writable, configurable, enumerable)
第一点:是否可以删除目标属性
let obj = Object.create(null);
Object.defineProperty(obj, 'name', {
value:'zhuangzhuang',
configurable:true
})
console.log(obj.name);//'zhuangzhuang'
delete obj.name;
console.log(obj.name);//undefined
可见,当configurable为true的时,是可以删除该属性的。
let obj = Object.create(null);
Object.defineProperty(obj, 'name', {
value:'zhuangzhuang',
configurable:false
})
console.log(obj.name);//'zhuangzhuang'
delete obj.name;
console.log(obj.name);//'zhuangzhuang'
可见,当configurable为false的时,不会删除该属性,并且不报错。
第二点:是否可以再次修改属性的特性(writable, configurable, enumerable)
var obj = {}
//第一种情况:configurable设置为false,不能再次修改特性。
Object.defineProperty(obj,"newKey",{
value:"hello",
writable:false,
enumerable:false,
configurable:false
});
//重新修改特性
Object.defineProperty(obj,"newKey",{
value:"hello",
writable:true,
enumerable:true,
configurable:true
});
console.log( obj.newKey ); //报错:Uncaught TypeError: Cannot redefine property: newKey
//第二种情况:configurable设置为true,可以再次修改特性。
Object.defineProperty(obj,"newKey",{
value:"hello",
writable:false,
enumerable:false,
configurable:true
});
//重新修改特性
Object.defineProperty(obj,"newKey",{
value:"hello",
writable:true,
enumerable:true,
configurable:true
});
console.log( obj.newKey ); //hello
该方法与Object.defineProperty相似,只不过该方法可以一次性操作多个属性
var obj = {};
Object.defineProperties(obj, {
'property1': {
value: true,
writable: true
},
'property2': {
value: 'Hello',
writable: false
}
// etc. etc.
});