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

相关推荐
里欧跑得慢14 分钟前
CSS 模块化架构的演进:BEM、CSS Modules 到 CSS-in-JS 的反思
前端·css·flutter·web·css-in-js
IT_陈寒26 分钟前
Vue的computed属性把我坑惨了,原来我一直用错姿势
前端·人工智能·后端
小灰灰搞电子1 小时前
Rust+Slint 实现温度计源码分享
前端·rust·slint
计算机魔术师1 小时前
面壁智能 OpenBMB 推出 MathForm,面向 Lean 4 数学自动形式化的开源框架、数据集与模型
前端
NeilCarmack2 小时前
Deepseek-harness增加桌面版端序列:第 2 讲 · spawn Electron:当前进程如何“交棒“
前端·javascript·electron
上海魁鲸科技有限公司2 小时前
APS高级排产系统到底有什么用?一文讲清功能、选型与落地建议
前端·microsoft·excel
陈随易2 小时前
Bun v1.4 更新总结:把浏览器、图片、定时任务和工程工具都装进一个运行时
前端·后端·程序员
东风破_4 小时前
TypeScript 高级类型进阶:keyof、Exclude、Record 与类型组合思想
前端·后端·typescript
DS随心转插件4 小时前
Grok生成的html怎么导出——AI导出鸭:大模型结构化输出的“最后一公里”工程化解构
前端·人工智能·ai·html·豆包·deepseek·ai导出鸭
এ慕ོ冬℘゜4 小时前
使用 jQuery 动态渲染表格与状态切换
前端·javascript·jquery