如何监听⼀个对象所有属性的变化
监听对象的属性变化,可以使⽤Object.defineProperty、Proxy等
如果您还不了解Object.defineProperty, 您可以先查看 来了解。
Object.definedProperty
1. 1 使⽤Object.defineProperty进⾏简单的对象监听
let obj ={}
let val = obj.name;
Object.defineProperty(obj,'name',{
// 存储描述符的⽅法来定义对象属性
set(newVal){
console.log("检测到了数据的变化",newVal)
val = newVal;
},
get(){
return val
}
});
setTimeout(()=>{
// 显然当对象的属性重新赋值(发⽣变化)时,会触发set⽅法,检测到数据的变化
obj.name ='a';
1. 2 深度监听对象属性
function observe(obj){
if(!obj ||typeof obj !='object'){
return
}
//每⼀层对象都绑定getter和setter
for(var i in obj){
definePro(obj,i,obj[i]);
}
}
function definePro(obj,key,value){
//递归调⽤
observe(value);
object.defineProperty(obj,key,{
get:function(){return value;},
set:function(newVal){
console.log("检测到了数据的变化",newVal);
value = newVal
}
})
}
var obj ={"a":{"name":{"fname":"Zi","Mname":"Y"},"age":18}}
observe(obj)
1. 2 监听数组的⽅法
Object.defineProperty⽆法监听数组对象上原型⽅法,包括push, pop, shift, unshift, splice, sort, reverse等
var arrayProto = Array.prototype
var arrayMethods = ate(arrayProto)
/** ate(proto[,properties])
* ate()⽅法创建了⼀个新对象,使得现有的对* 象来提供新创建的对象的__proto__
* 即:arrayMethods.__proto__ == Array.prototype //true
* structor == Array // true
*/
[
'push',
'pop',
'shift',
'unshift',
'splice',
'sort',
'reverse'
].forEach(function(item){
Object.defineProperty(arrayMethods,item,{
value:function mutator(){
//缓存原⽣⽅法,之后调⽤
console.log('array被访问');
/**
* original是arrayMethods 原型上的⽅法
* 这⾥把item⽤Obejct.defineProperty写到arrayMethods上
* 因此但凡⽤到了arrayMethods.item就会被检测到
* 这⾥以push为例,item取push arrayMethods.push是⼀个function
* 所传的参数arrayMethods.push(3) 3为arguments
*/
var original = arrayProto[item]
var args = Array.from(arguments)
//调⽤原型上的⽅法执⾏。
original.apply(this,args)
// console.log(this);
},
})
})
arrayMethods.push(2)
Proxy
1.1 Proxy的定义
Object.defineProperty不能直接监听数组的变化,⽽Proxy可以。
MDN 上 Proxy的定义: Proxy对象⽤于定义基本操作的⾃定义⾏为(如属性查、赋值、枚举、函数调⽤等)语法
const p = new Proxy(target,handler)
target: 要使⽤Proxy包装的⽬标对象(可以是任何类型的对象,包括原⽣数组,函数,甚⾄另⼀个代理)
handler: ⼀个通常以函数作为属性的对象,各属性中的函数分别定义了在执⾏各种操作时代理p的⾏为。
const handler ={
get:function(obj,prop){
return prop in obj ? obj[prop]:'数据不存在!'
}
}
const p =new Proxy({}, handler);
typeof arrayp.a =1;
p.b = undefined
console.log(p.c)// '数据不存在'
1.2 Proxy监听对象属性的变化
Proxy既能够监听到对象属性的变化,也能监听到数组的操作。
在使⽤Proxy前您可以先了解
var observe=(object)=>{
const handler ={
get(target,property,receiver){
try{
return new Proxy(target[property],handler);
}catch(err){
(target,property,receiver)
}
},
set(target,key,value,receiver){
console.log("===检测到了变化");
return Reflect.set(target,key,value,receiver);
}
};
return new Proxy(obj,handler)
};
var obj ={
foo:false,
a:{ x:{ y:4},b:[{c:false}]}
}
var test =observe(obj)
=5// ===检测到了变化
test.a.b.push("mm")// ===检测到了变化
//此时,test.a.b打印出来的结果Proxy{0:{c:false},1:'mm'} 说明它是个类数组 =5// ===检测到了变化
//查y属性时,调⽤getter访问器,返回x[y]
test.a.b.push("mm")// ===检测到了变化
//.push(),调⽤setter访问器, 原来b:Proxy{0:{c: false}},push后 key为1,
// 即Reflect.set(b,1,,"mm") 结果b:Proxy{0:{c:false},1:'mm'}
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。
发表评论