深究Reflect的本质——直接调用对象的基本方法

关于 Reflect(反射) 大多数人都不会陌生,MDN 文档里对其描述:Reflect 是一个内置的对象,它提供拦截 JavaScript 操作的方法。这些方法与 proxy handler (en-US) 的方法相同,Reflect 不是一个函数对象,因此它是不可构造的。

读了这段话,可能大家都会比较迷惑,这讲的是啥?对此产生了一些疑问:Reflect 的作用是啥?为什么要有他?

那么这篇文章将和大家一起去探究这些问题,理解 Reflect 的本质!

Reflect的本质

首先直接下结论,Reflect 的本质是直接调用对象的基本操作(基本方法),那么什么是对象的基本操作(基本方法)呢?我们可以去看下 ES 的官方文档,下面这个表格就罗列了对象的所有基本操作:

简单来说,在代码语法层面,无论我们怎么操作一个对象,实际上都是在调用这些基本方法!

举个例子,下面我们看一段的代码,读取对象中的属性和给对象设置属性,实际上内部间接调用了对象的基本方法 GET 和 SET:

把这段代码使用 Reflect 改写下,直接调用对象的基本方法:

两种方式其实效果是一样的,很明显可以看出使用 Reflect 反而更麻烦,代码可读性降低,那么为什么要使用 Reflect 呢?因此,接下来我们要探究 Reflect 的好处。

Reflect的好处

对于代码语句:obj.a 实际上会进行很多操作,包括其他操作和调用对象的基本方法(如上图),也就是所谓的间接操作,进行额外的步骤再调用对象的基本方法,因此这种方式在某些情况下是得不到直接调用对象的基本方法所产生的结果,如果我们不希望有这些额外的步骤存在,想要得到直接调用对象的基本方法所产生的结果,那么这个时候 Reflect 就派上用场了!

通过两个例子来说明:

例一

对象里面有个属性是一个方法,里面用到了 this,通过 obj.c 的方式去访问的话无法修改 this 指向,但是通过 Reflect.get 是可以做到的:

Reflect 中的 \[GET] 方法可以接受一个 Receiver 参数,这个参数可以指定 this 指向,使用 obj.c 这种方式里面很多额外的步骤,他不给你指定 this,而使用 Reflect 可以通过传参的方式一步到位!

那么正常情况下其实我们是不需要写出这种代码的,毕竟可读性差,所以说 Reflect 的使用是需要在特地的场景下,不是啥场景都能用的,没必要反而更加麻烦,Reflect 搭配 Proxy 就是一个很好的使用场景,帮助我们解决问题,下文再聊两者的结合使用,这里接着看第二个例子。

例二

使用 Object.keys 获取对象的键:

如果对象里面有 Symbol 类型或者不可枚举的键,那么 Object.keys 是拿不到这些键的:

Object.keys 内部其实是调用了 \[GetOwnProperty] 方法,但是它也有很多额外的步骤,这些步骤里面排除了一些类型的属性,所以拿不到想要的结果,我们看下 Object.keys 内部做了哪些事:

可以看到内部做了很多操作,因此如果我们想要排除忽略这些额外的操作,直接拿到结果,使用 Reflect 即可

通过上面两个例子可以知道,其实 Reflect 在某些场景下是很有用的,用好 Reflect 是有助于开发的!

Proxy+Reflect

对 Reflect 有了比较深入的理解之后,再来研究下 Vue3 响应式原理中为什么要搭配使用 Proxy 和 Reflect?其实就是要解决只使用 Proxy 带来的问题。

先看段使用代理对象的代码,这种情况下用到了对象的三个属性,但是却只读取到 c

这是为什么呢?因为 proxy.c 返回的是原始对象 obj 中的 c,target 其实就是 obj,里面的 this 是指向 target 的,此时读取 a b 是收不到任何通知的,必须要读代理里面的 a b 才能收到通知,这个时候就需要修改 this 指向才行,上面已经提到过 Reflect.get 是可以修改 this 指向的。

使用 Reflect 修改代码如下:

这样便得到了我们想要的结果。

相信大家对 Reflect 的本质有了更加深入的理解,一句话概括 Reflect:直接调用对象的基本方法(基本操作)!

相关推荐
wuxinyan1237 分钟前
工业级大模型学习之路030:Streamlit 企业级智能体前端工作台
前端·学习·streamlit·智能体
修己xj16 分钟前
告别无效刷屏!TrendRadar:最快30秒部署的开源热点助手,让你只看真正关心的新闻
前端
anOnion1 小时前
构建无障碍组件之Slider Pattern
前端·html·交互设计
云水一下1 小时前
JavaScript 从零基础到精通系列:前世今生与编程启蒙
前端·javascript
月亮邮递员6161 小时前
Markdown语法总结
开发语言·前端·javascript
Kurisu5752 小时前
雾锁王国修改器下载2026最新
前端·修改器代码
Rain5092 小时前
mini-cc 的 MCP 协议:给 AI 装个 USB-C 接口
c语言·开发语言·前端·人工智能·架构·node.js·ai编程
向量引擎3 小时前
从零起步,如何打造专属向量引擎 API 中转工作流?
java·服务器·前端
丷丩3 小时前
MapLibre GL JS第27课:添加COG栅格源
javascript·map·mapbox·maplibre gl js
IT_陈寒3 小时前
Vue这个动态响应坑把我整不会了
前端·人工智能·后端