Object.defineProperty
-
接收3个参数,第一个参数是需要操作的对象,第二个参数是需要操作的对象属性名,第三个参数是一个配置对象,
-
这个配置对象里面有4个选项,如下
1.configurable:表示能否通过delete删除属性从而重新定义属性,能否修改属性的特性,或者能否把属性修改为访问器属性,默认值为false。 2.enumerable:表示能否通过for in循环访问属性,默认值为false 3.writable:表示能否修改属性的值。默认值为false。 4.value:包含这个属性的数据值。默认值为undefined。
在调用Object.defineProperty()方法创建一个新属性时,如不指定前三个属性字段,默认值都为false, 如果是修改已定义的属性时,则没有此限制
// 表示在obj这个对象里新增一个d属性,属性值为10,可写,可更改,可迭代
Object.defineProperty(obj,"d",{
value:10,
writable:true,
configurable:true,
enumerable:true
})
3.第三个参数配置里面还有2个可选键值get和set,这两个是函数,value和get当中只能有一个,set和writable当中只能有一个
//如果想通过Object.defineProperty里的get和set函数修改对象里原有的数据,需要使用一个第三方变量来进行转换
let temp=0
Object.defineProperty(obj,"c",{
// value:6,
// writable:false,
get(){
console.log('正在获取属性',this);
return temp //get的返回值会作为c属性的属性值
},
set(val){
console.log('正在设置属性',val);
// temp=val 将新值赋值给中间转换的值
}
})
当获取obj.c属性的时候,get可以捕获到,这时,执行get函数里面的逻辑代码,如果修改obj.c属性的值,set可以捕获到,这个时候执行set里面的逻辑代码,set接收一个参数,这个参数就是修改后的新值
Object.defineProperty()监听对象设置还可以通过闭包进行实现,通过闭包,就不用再额外设置一个中间变量
function defineReactive(target,key,val){
Object.defineProperty(target,key,{
// value:6,
// writable:false,
get(){
console.log(`正在获取${key}的属性`);
return val
},
set(newval){
console.log(`正在设置${key}的属性`,newval);
val=newval
}
})
}
defineReactive(obj,"a")
obj.a=6
console.log(obj);