问题引出
const obj = {
name: '张三',
age: 3,
get value() {
return this.name
}
}
const handler = {
get(target, key, receiver) {
return target[key]
}
}
const p = new Proxy(obj, handler)
const children = {
name: '李四',
age: 20
}
Object.setPrototypeOf(children, p)
console.log(children.value); // 输出的chileren.value 的值为 张三
在这里,我们使用Proxy
去代理 obj
对象, 然后创建一个children
对象, 并让children
对象的原型对象指向 代理对象p ,当我们去访问children.value
的时候,由于children自身没有value属性,那么他就会顺着原型链上去找, 找到 p , 读取 p.value ,由于 p代理了 obj , 就会调用handler 中的get 方法 , 返回target[key]
, 也就是 obj[value]
, 返回obj.name,得到的值自然也就是张三。
那么问题来了, 如果我们想要得到的值不是张三, 而是 chileren 自身的name属性, 也就是 李四, 这要怎么做呢?
引入Reflect.get
我们可以去MDN 查看一下对此方法的说明: Reflect.get()
Reflect.get(target, propertyKey[, receiver])
Reflect.get()
方法与从 对象 (target[propertyKey]
) 中读取属性类似,但它是通过一个函数执行来操作的。
-
target
需要取值的目标对象 -
propertyKey
需要获取的值的键值 -
receiver
如果target
对象中指定了getter
,receiver
则为getter
调用时的this
值。
重点在于最后一个, 对 receiver的描述 , 如果target
对象中指定了getter
,receiver
则为getter
调用时的this
值。这样看起来非常抽象, 我们不妨通过代码来解释一下这句话
const obj = {
name: '张三',
age: 3,
get value(){
console.log(this === children,"this === p"); // true
return this.name
}
}
const handler = {
get(target,key,receiver){
return Reflect.get(target,key,receiver) // 此处做了修改
}
}
const p = new Proxy(obj,handler)
const children = {
name: '李四',
age: 20
}
Object.setPrototypeOf(children,p)
console.log(children.value); // 李四
上述代码中,我们把 return target[key]
更改为了 Reflect.get(target,key,receiver)
,我们为obj指定了getter, 也就是 get value(){...} , 那么getter中的this就变为了receiver
关于为什么receiver不是proxy而是children
我们可以看MDN当中对receiver的描述 handler.get() | MDN
target
目标对象。property
被获取的属性名。receiver
Proxy 或者继承 Proxy 的对象- 我们在前面通过
Object.setPrototypeOf(children,p)
使得children 继承了Proxy对象, 那么自然的, receiver 就指向 children