方法一 Object.defineProperty
使用Object.defineProperty 的存储属性描述符来对属性的操作进行监听 举例代码:
const obj = {
name: "why",
age: 18
}
Object.keys(obj).forEach(key => {
let value = obj[key]
Object.defineProperty(obj, key, {
get: function() {
console.log(`监听到obj对象的${key}属性被访问了`)
return value
},
set: function(newValue) {
console.log(`监听到obj对象的${key}属性被设置值`)
value = newValue
}
})
})
obj.name = "kobe"
obj.age = 30
console.log(obj.name)
console.log(obj.age)
obj.height = 1.88
// 以上代码打印结果如下
// 监听到obj对象的age属性被设置值
// 监听到obj对象的name属性被访问了
// kobe
// 监听到obj对象的age属性被访问了
// 30
缺点:如果我们想监听更加丰富的操作,比如新增属性、删除属性,那么Object.defineProperty是无能为力的。而且这种方法改变了数据的属性 name和age的属性描述符从数据属性描述符变成了访问属性描述符。
方法二 Proxy
ES6中,新增了一个Proxy类,是用于帮助我们创建一个代理的: 如果我们希望监听一个对象的相关操作,那么我们可以先创建一个代理对象(Proxy对象),之后对该对象的所有操作,都通过代理对象来完成,代理对象可以监听我们想要对原对象进行哪些操作。
Proxy共有13个捕捉器
使用Proxy的set和get捕获器可以监听对象的设置和获取操作
示例代码如下:
const obj = {
name: "why",
age: 18
}
const objProxy = new Proxy(obj, {
// 获取值时的捕获器
get: function(target, key) {
console.log(`监听到对象的${key}属性被访问了`, target)
return target[key]
},
// 设置值时的捕获器
set: function(target, key, newValue) {
console.log(`监听到对象的${key}属性被设置值`, target)
target[key] = newValue
}
// 监听in的捕获器
has: function(target, key) {
console.log(`监听到对象的${key}属性in操作`, target)
return key in target
},
// 监听delete的捕获器
deleteProperty: function(target, key) {
console.log(`监听到对象的${key}属性in操作`, target)
delete target[key]
}
})
console.log(objProxy.name)
console.log(objProxy.age)
objProxy.name = "kobe"
objProxy.age = 30
console.log(obj.name)
console.log(obj.age)
// in操作符
console.log("name" in objProxy)
// delete操作
delete objProxy.name
// 以上代码运行结果
// 监听到对象的name属性被访问了 { name: 'why', age: 18 }
// why
// 监听到对象的age属性被访问了 { name: 'why', age: 18 }
// 18
// 监听到对象的name属性被设置值 { name: 'why', age: 18 }
// 监听到对象的age属性被设置值 { name: 'kobe', age: 18 }
// kobe
// 30
// 监听到对象的name属性in操作 { name: 'why', age: 18 }
// true
// 监听到对象的name属性delete操作 { name: 'why', age: 18 }
set和get分别对应的是函数类型;
set函数有四个参数:
- target:目标对象(侦听的对象);
- property:将被设置的属性key;
- value:新属性值;
- receiver:调用的代理对象; get函数有三个参数:
- target:目标对象(侦听的对象);
- property:被获取的属性key;
- receiver:调用的代理对象;