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

相关推荐
mayaairi8 分钟前
Vue2 组件通讯(三):全局事件总线、PubSub、插槽与组件实例属性
前端·javascript·vue.js
kyriewen1 小时前
面试官问我:AI 都能写代码了,前端凭什么还值 25K
前端·javascript·人工智能
风骏时光牛马2 小时前
AI源码分析:拆解模型底层实现逻辑
前端
BillKu2 小时前
全局样式变量:CSS 自定义属性(--border-color)和SCSS 变量($border-color)的说明
javascript·css·scss
IT_陈寒2 小时前
React子组件莫名其妙重渲染?你可能漏了这个Hook
前端·人工智能·后端
乘风gg2 小时前
DeepSeek V4.1 Flash 来了,明天中午 Flash 降价 60%
前端·ai编程·claude
默_笙2 小时前
❗ 给金鱼装记忆(上):从白板到笔记本,AI 的短期记忆生存指南
前端·javascript
酷酷的逗逗乐2 小时前
前端转 Agent 开发 · 第五节:Memory 会话记忆
前端·程序员
掘金挖土3 小时前
前端手摸手跑路之 AI 应用开发(二)
前端·后端
兜里只有三分钱~3 小时前
翻卡_3D 的仪式感,和三个让它穿帮的写法
javascript·css·3d