ES6 Proxy和Reflect

编程入门 行业动态 更新时间:2024-10-27 16:27:14

ES6 <a href=https://www.elefans.com/category/jswz/34/1765361.html style=Proxy和Reflect"/>

ES6 Proxy和Reflect

1.Proxy是什么?

Proxy 对象用于创建一个对象的代理,从而实现基本操作的拦截和自定义(如属性查找、赋值、枚举、函数调用等)。属于“元编程”,即对编程语言进行编程。

如对对象a进行拦截就 let p = new Proxy(obj,handler)在handler里面编写拦截逻辑;

又如有对象a和b,想要对对象a中实现拦截对象b的属性,就将对象b设置到对象a的原型上再编写拦截逻辑;

2.创建Proxy对象的两种基本语法

  • 创建对象的代理
const p = new Proxy(target, handler)
  • 创建一个可撤销的代理对象
const { proxy: p, revoke } = Proxy.revocable(data, handler)

3.创建的proxy的实例有三个属性

  • target: 要使用 Proxy 包装的目标对象(可以是任何类型的对象,包括原生数组,函数,甚至另一个代理)。
  • handler: 一个通常以函数作为属性的对象,各属性中的函数分别定义了在执行各种操作时代理 p 的行为。(获取或者设置属性等操作;handler函数触发时,handler函数里面的this指向handler函数)
  • IsRevoked:当前属性是否被撤销。const { proxy: p, revoke } = Proxy.revocable(data, handler)创建一个可撤销的代理对象

4.proxy的实例两个注意点:

4.1 handler函数:handler函数触发时,handler函数里面的this指向handler函数

        let obj = { a:1 };let handler = {get(target, property, receiver){console.log(this);return target[property];//get中需要返回对应属性}};let p =  new Proxy(obj,handler);console.log(p.a);//注意要通过代理对象获取才能触发 get拦截

 

4.2 IsRevoked属性

IsRevoked:当前属性是否被撤销。const { proxy: p, revoke } = Proxy.revocable(data, handler)创建一个可撤销的代理对象

通过const { proxy: p, revoke } = Proxy.revocable(data, handler)创建可被撤销的对象实例后,此时IsRevoked为false,p.a 去调用属性会返回;

当在调用revoke();方法用于撤销代理对象,调用后IsRevoked为true,p.a 去调用属性会报错;

        let obj = { a:1 };let handler = {};const { proxy, revoke } = Proxy.revocable(obj, handler);

 5.handler中的方法handler.get()

var p = new Proxy(target, {get (target, property, receiver) {}
})

5.1方法用于拦截对象的读取属性操作。

  • target表示目标对象
  • property 被获取的属性名
  • receiver 接收Proxy或者继承Proxy对象 receiver === p
        let obj = { a: 1, b: 2 };let handler = {get(target, property, receiver) {console.log(target, property, receiver);return target[property];}};let proxy = new Proxy(obj, handler);console.log(proxy.a);

 

5.2 receiver 表示get()方法中接收的对象或者继承自的proxy对象

这里的问题是代理对象proxy.name想要获取到的是obj1上的name。

5.3handler.get()方法会拦截目标对象的以下操作:

  • 访问属性:proxy[foo] 和 proxy.bar
  • 访问原型链上的属性:Object.create(proxy)[foo]
  • Reflect.get()访问属性

访问属性:proxy[foo] 和 proxy.bar

比如,使用Proxy代理对象obj2,并将proxy实例对象设置到obj1的原型上,则通过obj1就可以获取到Proxy代理后的obj2的属性。此时通过proxy.name就可以获取到obj2的属性name值"lmf"

        let obj1 = { a: 1, b: 2, name: 'allen' };let obj2 = {name: 'lmf',get value() {return this.name}}let handler = {get(target, property, receiver) {return target[property];// return Reflect.get(target, property, receiver);}};let proxy = new Proxy(obj2, handler);// 将obj2的属性设置到obj1的原型上,则通过obj1就可以获取到obj2的属性Object.setPrototypeOf(obj1, proxy);console.log(obj1);console.log(obj1.value);//lmf

 其实这里obj1.name应该为allen才对,可以通过return Reflect.get(target, property, receiver);设置,类似与改变this指向为目标对象target也就是obj1

        let obj1 = { a: 1, b: 2, name: 'allen' };let obj2 = {name: 'lmf',get value() {return this.name}}let handler = {get(target, property, receiver) {return Reflect.get(target, property, receiver);}};let proxy = new Proxy(obj2, handler);// 将obj2的属性设置到obj1的原型上,则通过obj1就可以获取到obj2的属性Object.setPrototypeOf(obj1, proxy);console.log(obj1);console.log(obj1.value);//lmf

 访问原型链上的属性:Object.create(proxy)[foo]

        // 访问原型链上的属性:Object.create(proxy)[foo]let obj1 = { foo:'foo' };let handler = {get(target, property, receiver) {console.log("触发了");return target[property]}};let proxy = new Proxy(obj1, handler);const p = Object.create(proxy);console.log(p['foo']);

 Reflect.get(proxy, property)访问属性

        //  Reflect.get()访问属性let obj1 = { foo: 'foo' };let handler = {get(target, property, receiver) {console.log("触发了");return target[property]}};let proxy = new Proxy(obj1, handler);Reflect.get(proxy, 'foo')

6.handler中的方法handler.set()

 handler.set() 方法是设置属性值操作的捕获器。

const p = new Proxy(target, {set: function(target, property, value, receiver) {}
});

该方法会拦截目标对象的以下操作

1. 指定属性值:proxy[foo] = bar 和 proxy.foo = bar

2. 指定继承者的属性值:Object.create(proxy)[foo] = bar

3. Reflect.set()

        let obj1 = {myTime : "1697683657936"}let handler = {set(target, property, value){let setTime = value + new Date().getTime();target[property] = setTime;}}let proxy = new Proxy(obj1,handler);proxy.myTime = "此时的时间戳是:";console.log(proxy.myTime);

7.利用proxy实现的功能

7.1 验证对象的传值

需要实现的功能

1. 验证age属性的数据类型是否为整数

  2. 验证值的范围是否小于等于200

        // 需要实现的功能// 1. 验证age属性的数据类型是否为整数// 2. 验证值的范围是否小于等于200let user = {age: 100}let handler = {set(target,property,value){if(property==='age'){if(!Number.isInteger(value)){throw new TypeError("age的值必须是整数");}if(value>200){throw new RangeError("age的值不能超过200");}}}}let proxy = new Proxy(user,handler);// proxy.age = 22.3;proxy.age = 300

7.2通过属性查找数组中的特定对象

 需要实现的功能

var data = [{ name: 'Firefox'    , type: 'browser' },{ name: 'SeaMonkey'  , type: 'browser' },{ name: 'Thunderbird', type: 'mailer' }
]

1. 通过索引返回对应数据 proxy[0]

2. 通过number属性返回数组长度 proxy.number

3. 通过name获取对应的数据 proxy['Firefox']

4. 通过type返回对应的数据 proxy['browser']

5. 通过types返回data中的type products.types

        var data = [{ name: 'Firefox', type: 'browser' },{ name: 'SeaMonkey', type: 'browser' },{ name: 'Thunderbird', type: 'mailer' }]let handler = {get(target, property) {// 2. 通过number属性返回数组长度 proxy.numberif (property === 'number') {return target.length;}let result = [];target.forEach((item, index) => {// 1. 通过索引返回对应数据 proxy[0]if (property == index) {return result.push(item);}// 3. 通过name获取对应的数据 proxy['Firefox']if (property === item.name) {return result.push(item);}// 4. 通过type返回对应的数据 proxy['browser']if (property === item.type) {return result.push(item);}// 5. 通过types返回data中的type products.typesif (property === 'types') {result.push(item.type);result = [...new Set(result)]}});return result;}}let proxy = new Proxy(data, handler);console.log(proxy[0]);console.log(proxy.number);console.log(proxy['Firefox']);console.log(proxy['browser']);console.log(proxy['types']);

更多推荐

ES6 Proxy和Reflect

本文发布于:2023-12-07 10:03:47,感谢您对本站的认可!
本文链接:https://www.elefans.com/category/jswz/34/1670931.html
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。
本文标签:Proxy   Reflect

发布评论

评论列表 (有 0 条评论)
草根站长

>www.elefans.com

编程频道|电子爱好者 - 技术资讯及电子产品介绍!