外观
参考文章
js中为什么Proxy一定要配合Reflect使用_javascript技巧_脚本之家
Proxy作用
Proxy是ES6新增的内置对象,它的功能和名字一样,就是为了代理,它可以代理一个普通对象,生成一个代理对象,其功能远比Object.defineProperty强大,比如:
javascript
const obj = {name: '小李'}
const proxy = new Proxy(obj, {}) // 这里的handlers给个空对象,那么这个代理的所有操作都会和源对象obj同步handlers的作用和常见的handler
handlers是Proxy的重点部分,可以通过各种handler(陷阱)来对用户操作做出一系列的操作,最简单的即是get陷阱:
javascript
const obj = {name: '小李'}
const proxy = new Proxy(obj, {
get(target, key, receiver){
// target是代理源对象
// key是这被请求的对象的key
// receiver是实际触发get陷阱的对象,通常是代理源对象
return target[key]
}
})上面的代理即是原封不动的还原了对象获取属性的过程,get陷阱中可以做其他一系列比如拦截操作
除了最常见的get handler,Proxy一共提供了以下handler:
- handler.apply()
- handler.construct()
- handler.defineProperty()
- handler.deleteProperty()
- handler.get()
- handler.getOwnPropertyDescriptor()
- handler.getPrototypeOf()
- handler.has()
- handler.isExtensible()
- handler.ownKeys()
- handler.preventExtensions()
- handler.set()
- handler.setPrototypeOf()
get handler的参数
handler接收三个参数
- target ------------- 代理源对象
- key --------------劫持到的当前调用的key
- receiver ------- Proxy 或者继承 Proxy 的对象
对于target和key没什么好说的,比较简单,对于receiver参数在MDN上的解释是:Proxy 或者继承 Proxy 的对象
它会劫持proxy.xx、proxy[xx]、以及Object.create(proxy)[xx]
前两个就是最普通的对象获取方法,容易理解,这时receiver就是代理对象proxy
javascript
const obj = {name: '小李'}
const proxy = new Proxy(obj, {
get(target, key, receiver){
receiver === proxy // true
return target[key]
}
})如果对于以下代码就不对劲了
javascript
const obj = { name: "小李" };
Object.defineProperty(obj, "fullName", {
get() {
console.log("this", this); // {name: '小李'}
return this.name;
},
});
const proxy = new Proxy(obj, {
get(target, key, receiver) {
console.log(receiver === proxy); // false
return target[key];
},
});
const newObj = {
name: '李华',
};
// 设置obj继承与parent的代理对象proxy
Object.setPrototypeOf(obj, proxy);
console.log(newObj.fullName); // 小李对于原型链继承proxy的对象newObj上没有fullName,于是会顺着原型链往上找,找到了proxy有get陷阱,于是触发get函数,此时的get函数的target指向的是obj,于是就变成获取obj的fullName自然获取的是小李,但是我们希望的是返回的是李华,因为是newObj调用的,期望this指向当前调用者
这时就需要Reflect登场了
java
...
const proxy = new Proxy(obj, {
get(target, key, receiver) {
console.log(receiver === proxy); // false
- return target[key];
+ return Reflect(target, key, receiver)
},
});
...这里的receiver指向的是newObj,绑定给Reflect后,其修改了get函数中的this指向,获取的就是李华了
这里的Reflect使用类似于函数的call方法能改变this的指向,所以一般和proxy搭配使用防止出现this指向问题
