深究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:直接调用对象的基本方法(基本操作)!

相关推荐
审小匠OpenCPAi33 分钟前
银行流水核查怎么自动化?单边匹配、双向勾稽与图聚类异常检测的工程对比
java·前端·人工智能·python·审计
Revolution6137 分钟前
一个公共表格组件,是怎么一步步失控的
前端·前端工程化
mONESY39 分钟前
React useState 核心原理与最佳实践:从异步更新到性能优化全解
javascript
腻害兔1 小时前
【若依项目-产品经理视角】RuoYi-Vue-Pro 源码拆解:CRM 客户关系模块深度解析——从线索到回款,一套完整的 B2B 销售闭环是怎么搭的?
java·前端·javascript·vue.js·产品经理·ai编程
whyfail1 小时前
前端学 Spring Boot(2):一次点击,如何穿过整个后端?
前端·spring boot·后端
AI多Agent协作实战派2 小时前
AI多Agent协作系统实战(二十三):Agent读HEARTBEAT.md不读AGENTS.md——openclaw的文件加载之谜
前端·数据库·人工智能·uni-app
gis开发之家2 小时前
《Vue3 从入门到大神37篇》Vue3 源码详解(七):watch 与 watchEffect 源码对比——副作用是如何被追踪的?
javascript·前端框架·vue3·vue3源码
2601_955760073 小时前
如何用 Claude Opus 5 API 批量扩展长尾关键词和文章选题
前端·python·搜索引擎
KaMeidebaby3 小时前
卡梅德生物技术快报|bli亲和力检测gst:告别批量跑胶:BLI实时酶切监测技术加速GST融合蛋白下游流程优化
前端·网络·数据库·人工智能·算法
bloglin999993 小时前
langchain 和 langgraph 和 react
javascript·react.js·langchain