在Proxy和Reflect对象中的get、set方法的第三个参数是receiver,今天本文将讲述这个receiver到底是什么?
receiver翻译过来是接收者的意思,我们先看下MDN怎么解释这个参数的
proxy get receiver
Proxy或者继承Proxy的对象
当目前属性是一个getter访问器属性,通常情况下receiver参数为当前proxy本身。那么什么情况下receiver不是proxy本身?
我们先看一个简单的Proxy栗子,下面这个栗子我们使用了getter捕获器中的receiver参数。
let obj ={a:1}
let pObj=new Proxy(obj,{
get(target,key,receiver){
console.log("receiver",receiver); // receiver Proxy {a:1}
console.log("receiver===pObj",receiver===pObj); // true
return Reflect.get(target,key)
}
})
console.log(pObj.a); // 1
从这个栗子中可以得出当前receiver参数是当前代理对象。
我们再看看另外一个当Proxy对象被继承时的栗子
let obj ={a:1}
var pObj=new Proxy(obj,{
get(target,key,receiver){
return receiver
}
})
console.log(pObj.getReceiver); // pObj {a: 1}
let child = Object.create(pObj);
console.log(child.getReceiver); // child {}
当child对象被继承于pObj对象时,receiver参数会自动指向到继承它的对象。
到了这个我们已经这个Proxy中的receiver参数是什么了,接着我们看看Reflect中的receiver参数。
我们拿上面第一个栗子修改一下,把Reflect.get的第一个参数改为receiver,也即是当触发getter函数时,从receiver中获取对应的属性值。
let obj ={a:1}
let pObj=new Proxy(obj,{
get(target,key,receiver){
return Reflect.get(receiver,key)
}
})
console.log(pObj.a);
Uncaught RangeError: Maximum call stack size exceeded
细心的同学会发现这一段代码是一个死循环,在通过pObj.a时,触发了getter属性,又继续访问了receiver中的getter....一直嵌套下去导致无限循环。
这个时候就要Reflect.get的第三个参数传入Proxy中的receiver参数了,我们纠正下上面的代码。
let obj ={a:1}
let pObj=new Proxy(obj,{
get(target,key,receiver){
return Reflect.get(target,key,receiver)
}
})
console.log(pObj.a); // 1
这里的Reflect.get中的receiver参数是target对象中getter调用时的this值,这么说可能不是很明白,我们再通过一个栗子看看。
const obj = { get a() { return this.b; } };
const proxy = new Proxy(obj, {
get(target, key) {
return target[key]
}
})
console.log(Reflect.get(obj, "a")); // undefined
console.log(Reflect.get(obj, "a", { b: 2 })); // 2
在这里栗子中,我们给obj对象上设置了一个getter属性a,当我们访问a时返回当前this中的b,这里可以看到b是没有被定义的,直接访问为undefined,我们使用Reflect第三个参数receiver绑定a的this值为{ b: 2 },最终可以访问得到2。