记录关于Reflect.get的困惑

目录

    • 为什么p.bar不会无限循环?
    • 为什么这个p.bar又不会无限循环?
    • 结论

Reflect.get()的了解与学习,可以直接看Reflect.get() - JavaScript | MDN。
不过说实话,我在看完之后,仍然理解得不甚透彻。

那么你呢?你对其的理解又如何呢?如果让你回答以下例子的输出,你能够得出正确的答案吗?(答案在最后)
问题1:

    const obj = { bar: 1 }const value = Reflect.get(obj, 'bar', { bar: 2 })console.log('value', value)

问题2:

    const obj = {get bar() {return 1}}const value = Reflect.get(obj, 'bar', { bar: 2 })console.log('value', value)

问题3:

    const obj = {get bar() {return this.foo},foo:1}const value = Reflect.get(obj, 'bar', { bar: 2,foo:3 })console.log('value', value)

我的困惑,其实是在阅读《Vue.js设计与实现》中提到Reflect.get的代码时产生的。总的来说,我的困惑可以用以下的两个例子来表达:

为什么p.bar不会无限循环?

这个例子是这样的:

    const obj = { bar: 1 };const p = new Proxy(obj, {get(target, key, receiver) {return Reflect.get(target, key, receiver);}});console.log(p.bar)

先说说为什么我会得到p.bar会无限循环这个错误结论

  1. 读取p.bar会进入到getter,此时会return Reflect.get(target, key, receiver)
  2. 那么这时就会用receiver也就是p来替代target来读取key,也就是读取p.bar,从而又回到了第一步,从而导致无限循环。

但是,实际上这个例子是可以输出1的,并不存在无限循环,这个推导是错误的,那么实际上发生了什么呢?

以下是我理解这个例子发生的细节
obj是目标对象target,p是代理对象,在代理对象的get中,调用了Reflect.get(target, key, receiver),其中receiver其实就是代理对象p
当尝试读取p.bar时,实际上发生了以下步骤:

  1. 触发代理对象的get处理程序
  2. get处理程序中,调用了 Reflect.get(target,key,receiver) receiver就是代理对象本身
  3. 这时因为target[key]并不会触发getter,因此此时直接返回target[key]的值,也就是1。

至此流程就结束了,不存在循环的问题。

为什么这个p.bar又不会无限循环?

    const obj = {foo: 1,get bar() {return this.foo}}const p = new Proxy(obj, {get(target, key, receiver) {return Reflect.get(target, key, receiver)}})console.log(p.bar)

同样的,我先解释一下为什么我会推导出上面这个例子无限循环的错误结论

  1. 访问p.bar,会触发getter,执行return Reflect.get(target, key, receiver)
  2. 这时target[key]的读取会触发getter,因此会使用receiver替代target,也就是会用代理对象p来替代target
  3. 这时就相当于访问p.bar,就回到了第1步,从而导致无限循环。

正确的步骤

  1. 访问p.bar,会触发getter,执行return Reflect.get(target, key, receiver)
  2. 此时target[key]会访问对象的getter,因此Relect.get会将getter中的this设置为receiver也就是代理对象p,也就相当于return p.foo
  3. p.foo同样会触发代理对象get处理程序,执行return Reflect.get(target, key, receiver),但是此时的target[key]obj.foo,它不会访问对象的getter,因此会直接返回1

至此整个流程就结束了。

结论

  1. 使用Reflect.get(target, key, receiver)时,如果target[key]会访问对象的getter时,getter中的this会被设置为receiver
  2. 使用Reflect.get(target, key, receiver)时,如果target[key]不会访问对象的getter时,那么此时会直接返回目标对象上该属性的值,也就是target[key]

最后,回到开头的问题,
问题1:

    const obj = { bar: 1 }const value = Reflect.get(obj, 'bar', { bar: 2 })console.log('value', value) // value 1

问题2:

    const obj = {get bar() {return 1}}const value = Reflect.get(obj, 'bar', { bar: 2 })console.log('value', value) // value 1

问题3:

    const obj = {get bar() {return this.foo},foo:1}const value = Reflect.get(obj, 'bar', { bar: 2,foo:3 })console.log('value', value) // value 3

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/17872.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Promise.reslove().then中return值对.then执行顺序的影响

return的类型 Promise.reslove().then(){}中的返回值的三种情况: 基本数据类型带then方法的对象Promise.reslove(4) Promise.reslove().then(){return 4;return {then: function (reslove){reslove(4)}}return Promise.reslove(4)}首先看以下代码的输出&#xff1…

【C++】二叉搜索树

二叉搜索树 前言正式开始模拟实现树节点以及树框架增中序遍历查找删除 递归实现增删查查插删 析构拷贝构造赋值重载时间复杂度分析应用场景两道题 前言 本来想先把搁置了一个月的Linux讲讲的,但是里面有些内容需要用到一些比较高级的数据结构,用C写的话…

【业务功能篇61】SpringBoot项目流水线 dependencyManagement 标签整改依赖包版本漏洞问题

业务场景:当前我们项目引入了公司自研的一些公共框架组件,比如SSO单点登录jar包,文件上传服务jar包等公共组件,开发新功能,本地验证好之后,部署流水线,报出一些jar包版本的整改漏洞问题&#xf…

rust usize与i64怎么比较大小?

在Rust中, usize 和 i64 是不同的整数类型,它们的位数和表示范围可能不同。因此,直接比较 usize 和 i64 是不允许的。如果需要比较它们的大小,可以将它们转换为相同的类型,然后进行比较。 要将 usize 转换为 i64 &…

MongoDB 操作命令

创建database 有就切换没有创建 useMydatabase 显示数据库:show dbs显示该database下的 bson对象 show collections 显示该bson下的具体内容**mydatabase.mycollection.find()**查询该bson对象内容**且查询****mydatabase.mycollection.find({a:,b:})****或查询****…

二叉树OJ(C)

文章目录 1.单值二叉树1.1法一:无返回值1.2法二:有返回值 2.相同的树3.对称二叉树4.二叉树的前序遍历5.二叉树的中序遍历6.二叉树的后序遍历7.另一棵树的子树8.二叉树遍历 1.单值二叉树 1.1法一:无返回值 struct TreeNode {int val;struct …

Virtualbox虚拟机中Ubuntu忘记密码

1、首先重新启动Ubuntu系统,鼠标快速点一下Virtualbox虚拟机窗口获取焦点,然后按住shift键,以调出grub启动菜单。 2、根据提示按下键盘E键进入编辑模式,向下移动光标,将如下"ro quiet splash $vt_handoff"部…

SpringBoot集成jasypt,加密yml配置文件

SpringBoot集成jasypt,加密yml配置文件 一、pom配置二、生成密文代码三、配置3.1、yml加密配置3.2、密文配置3.3、启动配置3.4、部署配置 四、遇到的一些坑 最新项目安全检测,发现配置文件中数据库密码,redis密码仍处理明文状态 一、pom配置…

一套AI+医疗模式的医院智慧导诊系统源码:springboot+redis+mybatis plus+mysql

一套AI医疗模式的医院智慧导诊系统源码 相关技术: 技术架构:springbootredismybatis plusmysqlRocketMQ 开发语言:java 开发工具:IDEA 前端框架:Uniapp 后端框架:springboot 数 据 库:mys…

【win11+vs 2017+OpenCV4.5.5+Qt5.12配置】解决了过程中遇到的小问题

0.版本选择 由于Qt5无法与最新的vs2022兼容,扩展工具中一直显示不可用,所以将vs降级成vs2017。 在安装Qt的过程中,会选择安装Qt套件,其中就的MCVS 2017,说明vs2017是与qt兼容的。 当然也可以用qt creator这一原生IDE。…

LEARNING TO EXPLORE USING ACTIVE NEURAL SLAM 论文阅读

论文信息 题目:LEARNING TO EXPLORE USING ACTIVE NEURAL SLAM 作者:Devendra Singh Chaplot, Dhiraj Gandhi 项目地址:https://devendrachaplot.github.io/projects/Neural-SLAM 代码地址:https://github.com/devendrachaplot/N…

[软件工程] 全局分析规格说明书模板

1 价值需求 描述目标系统的价值需求,可以附上商业模式画布。 1.1 利益相关者 描述目标系统的利益相关者,包括终端用户、企业组织、投资人等。 1.2 系统愿景 描述利益相关者共同达成一致的愿景,该愿景的描述需要对准企业的战略目标。 1.3 系统…

机器学习分布式框架ray运行pytorch实例

Ray是一个用于分布式计算的开源框架,它可以有效地实现并行化和分布式训练。下面是使用Ray来实现PyTorch的训练的概括性描述: 安装Ray:首先,需要在计算机上安装Ray。你可以通过pip或conda来安装Ray库。 准备数据:在使用…

ES6基础知识九:你是怎么理解ES6中Module的?使用场景?

一、介绍 模块,(Module),是能够单独命名并独立地完成一定功能的程序语句的集合(即程序代码和数据结构的集合体)。 两个基本的特征:外部特征和内部特征 外部特征是指模块跟外部环境联系的接口…

Stable Diffusion AI绘画学习指南【插件安装设置】

插件安装的方式 可用列表方式安装,点开Extensions 选项卡,找到如下图,找到Available选项卡,点load from加载可用插件,在可用插件列表中找到要装的插件按install 按扭按装,安装完后(Apply and restart UI)应…

15、两个Runner初始化器和 springboot创建非web应用

两个Runner初始化器 两个Runner初始化器——主要作用是对component组件来执行初始化 这里的Component组件我理解为是被Component注解修饰的类 Component //用这个注解修饰的类,意味着这个类是spring容器中的一个组件,springboot应用会自动加载该组件。 …

【原创】IPTVC2实现方案(文末有demo)

前言: 名词解释: IPTVC2, 全称: 央视国际节目定价发布接口规范,标准版本当前最新为2.7.12 附赠资源链接,侵删:规范 规范中提供的样例,实现基于axis1.4(2006的时代宠物) 基于axis1版本的实现参考: Spring boot 集成Axis1.4 ,使用wsdd文件发…

【CSDN】

欢迎使用Mark编辑器 你好! 这是你第一次使用 Markdown编辑器 所展示的欢迎页。如果你想学习如何使用Markdown编辑器, 可以仔细阅读这篇文章,了解一下Markdown的基本语法知识。 新的改变 我们对Markdown编辑器进行了一些功能拓展与语法支持&#xff0c…

自动驾驶感知系统-全球卫星定位系统

卫星定位系统 车辆定位是让无人驾驶汽车获取自身确切位置的技术,在自动驾驶技术中定位担负着相当重要的职责。车辆自身定位信息获取的方式多样,涉及多种传感器类型与相关技术。自动驾驶汽车能够持续安全可靠运行的一个关键前提是车辆的定位系统必须实时…

【数学建模】——拟合算法

【数学建模】——拟合算法 拟合算法定义:与插值问题不同,在拟合问题中不需要曲线一定经过给定的点。拟合问题的目标是寻求一个函数(曲线),使得该曲线在某种准则下与所有的数据点最为接近,即曲线拟合的最好&…