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

相关推荐
zwjapple1 小时前
docker-compose一键部署全栈项目。springboot后端,react前端
前端·spring boot·docker
像风一样自由20203 小时前
HTML与JavaScript:构建动态交互式Web页面的基石
前端·javascript·html
aiprtem4 小时前
基于Flutter的web登录设计
前端·flutter
浪裡遊4 小时前
React Hooks全面解析:从基础到高级的实用指南
开发语言·前端·javascript·react.js·node.js·ecmascript·php
why技术4 小时前
Stack Overflow,轰然倒下!
前端·人工智能·后端
GISer_Jing4 小时前
0704-0706上海,又聚上了
前端·新浪微博
止观止5 小时前
深入探索 pnpm:高效磁盘利用与灵活的包管理解决方案
前端·pnpm·前端工程化·包管理器
whale fall5 小时前
npm install安装的node_modules是什么
前端·npm·node.js
烛阴5 小时前
简单入门Python装饰器
前端·python
袁煦丞5 小时前
数据库设计神器DrawDB:cpolar内网穿透实验室第595个成功挑战
前端·程序员·远程工作