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方法的。

相关推荐
Luna-player4 分钟前
前端中stylus是干嘛用的
前端·css·stylus
CHQIUU20 分钟前
解决 npm 全局安装 EACCES 权限问题(macOS 篇)
前端·macos·npm
程序员鱼皮21 分钟前
OpenClaw接入飞书保姆级教程,几分钟搞定手机养龙虾!
前端·人工智能·后端
紫_龙38 分钟前
最新版vue3+TypeScript开发入门到实战教程之vue3与vue2语法优劣对比
前端·javascript·typescript
SouthRosefinch1 小时前
一、HTML简介与开发环境
开发语言·前端·html
全栈小51 小时前
【前端】Vue 组件开发中的枚举值验证:从一个Type属性错误说起
前端·javascript·vue.js
Joker Zxc1 小时前
【前端基础(Javascript部分)】4、JavaScript的分支语句
开发语言·前端·javascript
IT_陈寒1 小时前
JavaScript 性能优化的5个隐藏技巧:90%开发者都不知道的实战方案!
前端·人工智能·后端
꧁꫞꯭零꯭点꯭꫞꧂2 小时前
G6绘制机柜 以及机柜设备的demo
前端·javascript·vue.js
C澒2 小时前
供应链产研交付提效:前端多业务线新增样板间页面统计方案
前端·mr