问题
Reflect.get三个参数target
, key
, receiver
,前两个好理解,第三个是什么意思呢?哪些场景下会用到呢?本文尝试解释下这个问题。
解释
首先搬出MDN对应Reflect.get
第三个参数recevier
的解释:
Reflect(target, key, recevier)中,如果
target
对象中指定了getter
,receiver
则为getter
调用时的this
值。
我们先定一个原始对象obj
:
js
const obj = {
hello: 1
}
根据MDN的描述,receiver
是用来指定原始对象中getter
的this
。因此obj
需要增加一个getter
属性world
,同时在getter
方法使用this
。
js
const obj = {
hello: 1,
get world() {
return this.hello
}
}
console.log(obj.world) // 1
这样一个符合条件的原始对象例子有了。访问obj.world
输出1。
那下面的代码呢?
js
const obj2 = {
hello: 2
}
console.log(Reflect.get(obj, 'world', obj2)); // 2
结果返回的是2。这里解释下原因:
- 当前
Reflect.get
的receiver
为obj2
,obj2
有一个属性hello
为2; - 根据MDN的描述,
receiver
为getter
调用的this
值,因此obj
中getter
属性的this
指向obj2
。 - 当读取
obj
的world
属性时,返回this.hello
,因此返回的为obj2
的hello
值。
使用场景
通常在Proxy
中我们如下返回原始对象的属性值:
js
const pObj = new Proxy(obj, {
get(target, key, receiver) {
console.log('Proxy key:', key)
return target[key]
}
})
pObj.world; // 读取代理对象的world属性
// 输出
// Proxy key: world
因为读取了pObj
的属性world
,因此会进入到get
方法,所以输出如上。
当然我们也可以通过Reflect.get
返回属性值:
js
const pObj = new Proxy(obj, {
get(target, key, receiver) {
console.log('Proxy key:', key)
return Reflect.get(target, key, receiver)
}
})
pObj.world; // 读取代理对象的world属性
// 输出
// Proxy key: world
// Proxy key: hello
通过Reflect.get
的调用,多输出了一行hello
。原因如下:
- 首先得知道下
Proxy
中的get
方法中也有一个reciever
,根据MDN的描述。它表示的就是当前的Proxy
对象pObj
。 - 因此
Reflect.get(target, key, receiver)
等价于Reflect.get(target, key, pObj)
,读取world
的时候的时候,返回this.hello
,当前的this
又指代的是pObj
,因此读取了pObj.hello
。 pObj.hello
的读取再次进入了代理对象的get
方法中,因此输出了第二行的hello
。
通过上面两种方式的对比,可以知道,如果使用target[key]
的方法返回属性值,我们无法拦截到this.hello
的读取操作;而通过Reflect.get
则可以。
总结
Reflect.get(target, key, receiver)
方法中,receiver
指代target
对象中getter
属性的this值。- 相关代码:github.com/wdskuki/js-...