TS 进阶用法 proxy & Reflect(TS-23)

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 属性,如果没有该属性返回 undefined

Reflect.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);
JavaScript 的 Proxy 和 Reflect 是 ECMAScript 6 引入的新特性。它们可以一起使用来创建代理对象,以拦截对对象的访问和操作,从而提供更灵活的控制和定制行为。 Proxy 是一个 JavaScript 内置对象,它允许你拦截并定义基本操作的自定义行为,例如属性访问、函数调用、对象构造等。Reflect 是一个 JavaScript 内置对象,它提供了一组方法,用于在 Proxy 对象上执行默认行为。 使用 Proxy 和 Reflect,开发人员可以创建具有自定义行为的对象。例如,您可以使用 Proxy 拦截对对象属性的访问,并在 Reflect 上调用默认行为来获取或设置该属性的值。这种灵活性使得开发人员能够更好地控制和自定义应用程序的行为。 下面是一个简单的例子,展示了如何使用 Proxy 和 Reflect 创建一个代理对象: ```javascript const obj = { name: 'John', age: 30 }; const handler = { get(target, prop, receiver) { console.log(`Getting ${prop} property`); return Reflect.get(target, prop, receiver); }, set(target, prop, value, receiver) { console.log(`Setting ${prop} property to ${value}`); return Reflect.set(target, prop, value, receiver); } }; const proxyObj = new Proxy(obj, handler); console.log(proxyObj.name); proxyObj.age = 35; ``` 在上面的例子中,我们创建了一个名为 obj 的对象,并将其传递给一个名为 handler 的代理处理程序。处理程序定义了对 get 和 set 操作的拦截,其中在每个操作中都使用 Reflect 调用默认行为。然后,我们创建了一个名为 proxyObj 的代理对象,并将其设置为 obj 的代理。最后,我们访问了 proxyObj 的属性,并将其设置为一个新值。 当我们运行上面的代码时,我们会看到以下输出: ``` Getting name property John Setting age property to 35 ``` 从输出中可以看出,代理处理程序成功地拦截了对代理对象的访问和操作,并使用 Reflect 调用了默认行为。这样,我们就可以更好地控制和自定义我们的应用程序行为。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值