Proxy receiver的使用,为什么需要Reflect对象

为什么需要receiver

最近在看回阮一峰老师的ECMAScript6入门,在Proxy一章中提到的13种拦截方法,其中get 和 set 都有一个receiver参数,原文的解释是:原始的读/赋值操作所在的那个对象,并且有两段代码示例:

ini 复制代码
const proxy = new Proxy({}, {
  get: function(target, key, receiver) {
    return receiver;
  }
});
proxy.getReceiver === proxy // true

这一段就是解释了receiver指向原始操作对象。但是target不也是跟receiver一个指向吗,那为什么还要receiver呢,接着看第二段示例代码:

ini 复制代码
const proxy = new Proxy({}, {
  get: function(target, key, receiver) {
    return receiver;
  }
});

const d = Object.create(proxy);
d.a === d // true

这里用了一个ProxyObject.create创建d对象,那么在读取d对象的时候,由于没有自身属性,就会去原型上找,找到proxy,然后被get拦截,返回receiver,这里的receiver却是指向了d对象。

那么很明显,在这类型问题上,指向就是receiver所要解决的问题了

实际问题

既然是指向问题,那么this就是我们始终绕不开的话题,我们就用this指向来举个例子。

js 复制代码
let user = {
  _name: 'user',
  get name() {
    return this._name;
  }
};

let userProxy = new Proxy(user, {
  get(target, propKey, receiver) {
    return target[propKey];
    // return Reflect.get(target, propKey);
  }
});

let admin = Object.create(userProxy);
admin._name = 'admin';

console.log(admin.name); // user

发现问题

这里的user用了_name表示name是私有的,并且使用了get函数来获取,然后Proxy拦截读取操作,返回值直接使用了对象取值的方式。然后用声明admin去继承userProxy,并且给admin自己取名为admin

然而在读取admin.name时却发现名字是user,这里非常简单,因为Proxy.get中的targetuser,所以返回的是user._name

同样的使用Reflect对象去还原原生行为,但不传入receiveradmin.name依然是user

解决问题

当我们传入receiver

js 复制代码
let user = {
  _name: 'user',
  get name() {
    return this._name;
  }
};

let userProxy = new Proxy(user, {
  get(target, propKey, receiver) {
    return Reflect.get(target, propKey, receiver);
  }
});

let admin = Object.create(userProxy);
admin._name = 'admin';

console.log(admin.name); // admin

admin.name就变成了admin,这才是我们想要的结果。

为什么要用Reflect对象

这里还有一点,我们直接target[propKey]的方式能用上receiver吗?

对象的get函数,Proxy.get需要返回一个修改了this指向的函数,那可以返回target[propKey].bind(receiver)吗?

答案是不可以的,对象的get函数是比较特殊的存在,表现形式是函数,但他其实是个属性,当你访问target[propKey]的时候,他已经是user字符串了,自然的在它的原型上是找不到bind方法的。

相关推荐
@PHARAOH11 分钟前
HOW - Kratos 入门实践(二)- 概念学习
前端·微服务·go
We་ct4 小时前
LeetCode 77. 组合:DFS回溯+剪枝,高效求解组合问题
开发语言·前端·算法·leetcode·typescript·深度优先·剪枝
KerwinChou_CN4 小时前
什么是流式输出,后端怎么生成,前端怎么渲染
前端
爱上妖精的尾巴4 小时前
8-18 WPS JS宏 正则表达式-边界匹配
开发语言·javascript·正则表达式·wps·jsa
爱上妖精的尾巴4 小时前
8-20 WPS JS宏 正则表达式-懒惰匹配
服务器·前端·javascript
网络点点滴4 小时前
组件通信props方式
前端·javascript·vue.js
二十雨辰4 小时前
[小结]-线上Bug监控
前端·bug
前端技术4 小时前
【鸿蒙实战】从零打造智能物联网家居控制系统:HarmonyOS Next分布式能力的完美诠释
java·前端·人工智能·分布式·物联网·前端框架·harmonyos
CHU7290355 小时前
指尖践行环保——旧衣服回收小程序前端功能玩法详解
前端·小程序
weixin_443478515 小时前
flutter组件学习之Flex / Expanded弹性布局组件
javascript·学习·flutter