proxy:对象代理(是ES6新增的对象拦截器,能够监听到一个对象的变化)
Reflect:配合proxy来操作对象
Proxy
Proxy 对象用于创建一个对象的代理,从而实现基本操作的拦截和自定义(如属性查找、赋值、枚举、函数调用等)
target
要使用
Proxy
包装的目标对象(可以是任何类型的对象,包括原生数组,函数,甚至另一个代理)。
handler
一个通常以函数作为属性的对象,各属性中的函数分别定义了在执行各种操作时代理
p
的行为。
handler.get()
本次使用的 get属性读取操作的捕捉器。
handler.set()
本次使用的 set属性设置操作的捕捉器。
Reflect
与大多数全局对象不同
Reflect
并非一个构造函数,所以不能通过 new 运算符对其进行调用,或者将Reflect
对象作为一个函数来调用。Reflect
的所有属性和方法都是静态的(就像 Math 对象)Reflect.get(target, name, receiver)
Reflect.get
方法查找并返回target
对象的name
属性,如果没有该属性返回 undefinedReflect.set(target, name,value, receiver)
Reflect.set
方法设置target
对象的name
属性等于value
。
type Person = {
name:string,
age:number,
text:string
}
const proxy = (object:any,key:any)=>{//我们要自己实现proxy啦
return new Proxy(object,{
get(target,prop,receiver){
console.log('================>get',prop);
//prop就是一个key,target就是地下那个man的对象,receiver是跟target一样的值,防止上下文错误的
return Reflect.get(target,prop,receiver)//这里刚好对应的也是这三个参数
},
set(target,prop,value,receiver){//多了一个value,因为我们要设置值
//日志
console.log('================>set',prop);
return Reflect.set(target,prop,value,receiver)
}
})
}
//日志监听函数
//由于我们要监听man里面的内容,所以这里可以使用联合类型
const logAccess = <T>(object: T ,key:"name" | "age" | "text"):T =>{//为了使其灵活度高一点,我们不使其object等于Person,而是为泛型T,使用的时候再去设置
return proxy(object,key)
}
let man:Person = ({
name:"小满",
age:22,
text:"三秒真男人"
})
let man2 = logAccess({
name:"小余"
},'name')
man.age = 30//走set
man.age//走get
console.log(man)
泛型优化
const logAccess = <T>(object: T ,key:keyof T):T =>{//为了使其灵活度高一点,我们不使其object等于Person,而是为泛型T,使用的时候再去设置。key也不固定死,而是使用keyof,将我们传入的对象推断为联合类型
return proxy(object,key)
}
let man2 = logAccess({
name:"小余",
id:925
},'id')//就可以动态的去约束类型
let man2 = logAccess({
name:"小余",
id:925
},'id2')//报错,因为我们类型里没有id2
优化完整版
type Person = {
name: string,
age: number,
text: string
}
const proxy = (object: any, key: any) => {
return new Proxy(object, {
get(target, prop, receiver) {
console.log(`get key======>${key}`);
return Reflect.get(target, prop, receiver)
},
set(target, prop, value, receiver) {
console.log(`set key======>${key}`);
return Reflect.set(target, prop, value, receiver)
}
})
}
const logAccess = <T>(object: T, key: keyof T): T => {
return proxy(object, key)
}
let man: Person = logAccess({
name: "小满",
age: 20,
text: "我的很小"
}, 'age')
let man2 = logAccess({
id:1,
name:"小满2"
}, 'name')
man.age = 30
console.log(man);