介绍
Proxy 和 Reflect 内置对象从 ECMAScript 2015 开始支持,允许拦截并定义自定义行为。
语法
| 1 | const p = new Proxy(target, { ...traps }) | 
- traps- 被代理对象上的自定义行为。包含捕获器(操作发生时所对应的处理函数)的方法列表。
 
- target- 被代理的目标对象。
 
| 1 | const handler = { | 
使 Proxy 代理起作用,必须对 proxy 对象 进行操作,而不是原对象。
this 指向
- Proxy代理的原对象内部的- this指向其代理对象。- 1 
 2
 3
 4
 5
 6
 7
 8
 9- const target = { 
 m () {
 return this === proxy;
 }
 };
 const proxy = new Proxy(target, {});
 console.log(target.m()); // false
 console.log(proxy.m()); // true
- handler拦截函数内部的- this,指向的是- handler对象本身。- 1 
 2
 3
 4
 5
 6- const handler = { 
 get() {
 console.log(this === handler);
 }
 };
 new Proxy({}, handler).foo; // true
- 有些原生对象的内部属性,只有通过正确的 this才能获取。1 
 2
 3
 4
 5
 6
 7
 8
 9
 10
 11const target = new Date(); 
 new Proxy(target, {}).getDate(); // TypeError: this is not a Date object
 const handler = {
 get(target, prop) {
 const val = target[prop];
 return typeof val === 'function' ? val.bind(target) : Reflect.get(...arguments);
 }
 };
 const proxy = new Proxy(target, handler);
 console.log(proxy.getDate()); // 可以获取日期
receiver 指向
- get和- set捕获器函数的最后一个参数都是一个- receiver对象,指向当前代理对象。- 1 
 2
 3
 4
 5
 6- const proxy = new Proxy({}, { 
 get(target, key, receiver) {
 return receiver;
 }
 });
 proxy.getReceiver === proxy // true
- 但是,代理对象作为其他对象的原型被继承时,receiver会指向被继承的对象。1 
 2
 3
 4
 5
 6
 7
 8
 9
 10let obj; 
 const proxy = new Proxy({ foo: 3 }, {
 get(target, prop, receiver) {
 console.log(receiver === proxy, receiver === obj);
 return target[prop];
 }
 });
 console.log(proxy.foo); // true false 3
 obj = Object.create(proxy);
 console.log(obj.foo); // false true 3
- 在 handler拦截函数中,如果遇到target中有定义的getter,则getter中的this指向调用的target,即不会改变指向,但可以手动将其指向receiver。1 
 2
 3
 4
 5
 6
 7
 8
 9
 10
 11
 12
 13
 14
 15
 16const obj = { foo: 1 }; 
 const proxy = new Proxy({
 foo: 3,
 get info() {
 return this.foo;
 }
 }, {
 get(target, prop, receiver) {
 console.log(receiver === obj); // true
 console.log(target[prop]); // 3
 console.log(Reflect.get(target, prop)); // 3
 return Reflect.get(...arguments); // Reflect.get(target, prop, receiver)
 }
 });
 Object.setPrototypeOf(obj, proxy);
 console.log(obj.info); // 1
参考资料
本博客所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议。转载请注明来自 张坤的博客!
 评论