Object.defineProperty()
1. 基本使用
语法:Object.defineProperty(obj, key, descriptor:属性和方法)
obj:要进行操作的对象。
key:要定义或修改的属性的名称。
let obj = {}
Object.defineProperty(obj,'a',{
configurable: true //是否允许删除
enumerable:true //是否允许枚举
value:undefined //就是value值
writable:true //是否允许赋值
get() {} //获取的return的值
set(val) {} //修改的时候执行 val就是最新的值
})
使用
let obj = {
name: "张三",
age: 21
}
let keys = Object.keys(obj);
for (let i in keys) {
let key = keys[i];
Object.defineProperty(obj, key, {
get() {
return obj[key];
},
set(val) {
obj[key] = val;
}
})
}
obj.name = "李四";
看起来感觉上面的代码没有什么错误,但是试着运行一下吧~你会和我一样栈溢出。这是为什么呢?让我们聚焦在set方法里,我们在修改obj身上的name属性时,会触发set方法,set方法里又继续修改obj属性的值,导致递归调用,最终栈溢出。
这也引出了我们下面的方法,我们需要设置一个中转data,来让set修改data的值,get在返回出data的属性值。
而不是直接修改obj导致导致递归调用。
let obj = {
name: "张三",
age: 21
}
let data = {}
let keys = Object.keys(obj);
for (let i in keys) {
let key = keys[i];
Object.defineProperty(obj,key,{
get() {
return data[key];
},
set(val) {
data[key] = val;
}
})
}
obj.name = "李四"
监听对象上的多个属性
在实际情况中,我们通常需要一次监听多个属性的变化。这时我们需要配合Object.keys(obj)进行遍历。这个方法可以返回obj对象身上的所有可枚举属性组成的字符数组。下面是该API一个简单的使用效果:
let obj = { name: "张三", age: 21 };
console.log(Object.keys(obj)); // console: ['name', 'age'];