Reflect.get() 详细介绍,并给出例子说明

Reflect.get() 是 JavaScript 的一个内置方法,它用于获取对象上某个属性的值。这个方法属于 Reflect 对象,它提供了一种方式来执行对象的属性访问操作,与直接使用点(.)或方括号([])访问属性的方式类似,但提供了更多的控制和灵活性。

Reflect.get() 方法接收三个参数:

  1. target:目标对象,即你想从中获取属性的对象。
  2. propertyKey:字符串或 Symbol 类型的属性名或键。
  3. receiver(可选):如果属性是一个 getter,则 receiver 是 getter 函数调用时的 this 值。如果省略该参数,则默认为 target

例子说明

示例 1:基本使用

const obj = {foo: 'Hello',bar: 42
};// 使用 Reflect.get() 获取属性 foo 的值
const fooValue = Reflect.get(obj, 'foo');
console.log(fooValue); // 输出: 'Hello'// 使用 Reflect.get() 获取属性 bar 的值
const barValue = Reflect.get(obj, 'bar');
console.log(barValue); // 输出: 42

示例 2:使用 getter

当属性是一个 getter 函数时,Reflect.get() 的第三个参数 receiver 会影响 getter 的执行上下文(即 this 的值)。

const obj = {_private: 'Secret',get secret() {return this._private;}
};// 使用 Reflect.get() 获取 secret 属性的值,并传递 obj 作为 receiver
const secretValue = Reflect.get(obj, 'secret', obj);
console.log(secretValue); // 输出: 'Secret'// 如果没有传递 receiver,或者 receiver 不是 obj,getter 函数中的 this 可能不会指向正确的对象
const incorrectSecretValue = Reflect.get(obj, 'secret', {});
console.log(incorrectSecretValue); // 输出: undefined,因为 _private 属性在 {} 上不存在

示例 3:使用继承属性

如果 target 对象继承了一个属性,Reflect.get() 也可以获取这个继承的属性。

class Parent {constructor() {this.parentProperty = 'Parent property';}
}class Child extends Parent {constructor() {super();this.childProperty = 'Child property';}
}const child = new Child();// 使用 Reflect.get() 获取继承的属性
const parentPropertyValue = Reflect.get(child, 'parentProperty');
console.log(parentPropertyValue); // 输出: 'Parent property'

示例 4:处理不存在的属性

如果尝试获取一个不存在的属性,Reflect.get() 会返回 undefined

const obj = {foo: 'Hello'
};// 尝试获取不存在的属性
const nonExistentValue = Reflect.get(obj, 'nonExistent');
console.log(nonExistentValue); // 输出: undefined

总结

Reflect.get() 提供了一种灵活且可控的方式来访问对象的属性。它允许你动态地指定目标对象、属性键和 getter 调用时的 this 值。这使得它在某些高级编程场景中特别有用,比如元编程、代理(Proxy)和反射(Reflection)API。在普通应用中,你通常会直接使用点(.)或方括号([])来访问对象的属性,但在需要更精细控制或处理复杂对象结构时,Reflect.get() 会是一个很好的选择。

附录1

在 JavaScript 的 Proxy 对象中,this 的绑定行为有点特殊。当通过 Proxy 访问对象的属性或方法时,如果这个属性或方法是一个函数,那么该函数内部的 this 绑定通常取决于如何调用这个函数。但是,当使用 Proxy 时,this 的绑定取决于 Proxyget 捕获器中 Reflect.get 的第三个参数 receiver

get 捕获器中,Reflect.get(target, property, receiver) 的作用类似于直接访问 target[property],但是它会确保正确的 this 绑定。receiver 参数通常是代理对象本身(userProxy),或者在某些情况下(比如当属性是在原型链上找到的时候),它可能是其他对象。

当你通过 userProxy 调用 greet 方法时,greet 方法内部的 this.namethis.age 访问会被 Proxyget 捕获器拦截。这是因为 greet 方法是作为 userProxy 的一个属性被调用的,而 userProxy 是一个 Proxy 对象。因此,任何对 userProxy 属性的访问都会触发 get 捕获器。

get 捕获器中,当 propertynameage 时,Reflect.get(target, property, receiver) 会被调用。这里的 target 是原始对象 user,而 receiver 通常是 userProxy(除非在原型链上找到属性)。因此,尽管 thisgreet 方法内部看起来是指向 user 的,但由于 Reflect.get 的使用,它实际上是指向 receiver,即 userProxy。不过,重要的是要理解 this 并不是直接绑定到 userProxy,而是 Reflect.get 在内部处理 this 绑定,使其表现得像是通过 userProxy 访问的。

greet 方法内部,this.namethis.age 的访问被拦截,并且 get 捕获器返回了相应的属性值。由于 this 在方法内部是通过 receiver 间接绑定的,因此即使 this 看起来指向 user,你仍然可以通过 Proxy 添加额外的逻辑,比如权限检查、日志记录等。

简而言之,this 在方法内部指向的是 user,但是 Proxyget 捕获器通过 Reflect.get 确保了正确的属性访问和可能的 this 绑定调整。当你通过 userProxy 调用方法时,this 的行为就像是通过 userProxy 访问的,尽管实际上 this 指向的是原始对象。

Proxyget 陷阱中,使用 Reflect.get(target, property, target)Reflect.get(target, property, receiver) 的区别在于第三个参数 receiver 的值。这个参数决定了在访问属性时 this 的绑定。

当你使用 Reflect.get(target, property, target) 时,你实际上是在告诉 Reflect.get 使用 target(即原始对象)作为 this 的绑定。这意味着,如果属性是一个 getter 方法(如 get age()),当这个方法内部使用 this 来访问其他属性(如 this._age)时,这些访问将直接针对 target 进行,而不会再次触发 Proxyget 陷阱。因此,this._age 的访问不会被拦截。

相反,当你使用 Reflect.get(target, property, receiver) 时,你提供了另一个对象作为 receiver。这通常会是 Proxy 对象本身(即 userProxy)。在这种情况下,如果属性是一个 getter 方法,并且这个方法内部使用 this 来访问其他属性,那么这些访问将会通过 Proxyget 陷阱进行。这是因为 this 现在绑定到了 receiver(即 userProxy),而不是 target。因此,任何通过 this 进行的属性访问都会被 Proxy 拦截。

这里是一个简化的例子来说明这个区别:

const user = {_age: 30,get age() {return this._age; // this 的值取决于 Reflect.get 的第三个参数}
};const userProxy = new Proxy(user, {get(target, property, receiver) {console.log(`Intercepted access to ${property}`);// 使用 target 作为 this 的绑定// return Reflect.get(target, property, target);// 使用 receiver 作为 this 的绑定return Reflect.get(target, property, receiver);}
});// 使用 target 作为 this 的绑定
// console.log(userProxy.age); // 输出: 30,并且不会打印 "Intercepted access to _age"// 使用 receiver 作为 this 的绑定
console.log(userProxy.age); // 输出: Intercepted access to age 和 Intercepted access to _age,然后是 30

在注释掉的代码中,当使用 target 作为 this 的绑定时,this._age 的访问不会触发 get 陷阱,因此只会打印 Intercepted access to age。而在未注释的代码中,当使用 receiver(即 userProxy)作为 this 的绑定时,this._age 的访问也会触发 get 陷阱,因此会打印 Intercepted access to ageIntercepted access to _age

这个特性使得 Proxy 极其灵活,因为它允许你精确控制 this 的绑定,并在必要时拦截通过 this 进行的属性访问。

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

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

相关文章

CCF区块链论文录用资讯--ICSE 2024

ICSE是CCF A类会议 (软件工程/系统软件/程序设计语言) 其2024录用了13篇区块链论文 Smart Contract and DeFi Security Tools: Do They Meet the Needs of Practitioners? 智能合约和 DeFi 安全工具:它们满足从业者的需求吗? St…

SegAnyGAussians(SAGA)项目配置和运行

GitHub项目地址:Jumpat/SegAnyGAussians: The official implementation of SAGA (Segment Any 3D GAussians) (github.com) 一、项目准备 1、下载原项目的zip包解压 2、下载third_party目录下的两个模块,放到对应目录下 3、下载预训练模型和数据集 数据…

非计算机专业,如何从事研发岗位的建议!

首先,非计算机专业的毕业生通过读研和专门的培训是完全可以进入IT行业的,目前IT行业内也有大量非计算机专业毕业的技术开发(研发)人员,其中有不少人也非常优秀,发展空间同样比较大。 虽然IT行业内整体的人才…

IPFS分布式存储系统

一、 引言 IPFS是InterPlanetary File System的缩写。它是一个分布式的网络传输协议,它可以把文件分成很多小块放到服务器的不同地方,然后用一种特别的方式来寻找和传输这些小块。这样,我们就可以更快、更安全、更抗容错了的存储文件了。 可能…

从小到大输出四个整数(C语言)

一、N-S流程图&#xff1b; 二、运行结果&#xff1b; 三、源代码&#xff1b; # define _CRT_SECURE_NO_WARNINGS # include <stdio.h>int main() {//初始化变量值&#xff1b;int a, b, c, d;int t 0;//提示用户&#xff1b;printf("请输入四个整数a b c d&…

python怎么判断整数

isinstance()函数 可以用来判断变量的类型&#xff0c;它返回的是一个布尔值&#xff0c;False or True。 >>>isinstance("123",str) >>>Flase >>>isinstance(123,int) >>>True >>>isinstance({123},list) >>&g…

【大数据】分布式文件系统HDFS

目录 1.什么是分布式文件系统 2.HDFS的特点 3.HDFS的核心概念 4.HDFS的体系结构 5.HDFS的配置建议 6.HDFS的局限性 7.HDFS的存储机制 7.1.数据冗余机制 7.2.错误与恢复 8.HDFS数据读写过程 1.什么是分布式文件系统 分布式文件系统是整个大数据技术的基础&#xff0c…

京东AI数字人“采销东哥”首秀观看量破2000万;天工 SkyMusic 音乐大模型开放公测

&#x1f989; AI新闻 &#x1f680; 京东AI数字人“采销东哥”首秀观看量破2000万 摘要&#xff1a;京东AI数字人“采销东哥”由京东云言犀打造&#xff0c;在其直播首秀中亮相并迅速吸引超2000万观看量。尽管“采销东哥”的外形和口音与创始人刘强东相似&#xff0c;但其直…

C语言的OJ判题机设计与实现

1. 接收判题入参 判题需要作答代码、测试输入和期望输出、编译器名称、时空限制。对于支持special judge的还需要传入是否为sj和sj代码。推荐使用消息队列&#xff0c;应对高并发的比赛情况会比较好。 但是消息队列是异步的&#xff0c;我为了快点实现能提交后在当前页面获得判…

量子密钥分发系统的设计与实现(二):光路子系统初步讨论

通过上一篇文章&#xff0c;我们对量子密钥分发系统的基本架构、硬件结构以及密钥分发流程进行了初步的总体介绍&#xff0c;从本文开始&#xff0c;我们就基于系统顶层的架构设计&#xff0c;开始从模块到器件&#xff0c;从硬件到软件开始详细讨论QKD系统的设计与实现。本文主…

双向链表详解

目录 带头双向循环链表带头双向循环链表的实现带头双向循环链表的功能实现创造新节点LTNode* CreateLTNode(LTDataType x)代码 初始化链表LTNode*LTInit(LTNode* phead)代码 打印链表void LTPrint(LTNode* phead)代码 链表尾插void LTPushBack(LTNode* phead, LTDataType x)代码…

C#语法知识之运算符

3、运算符 1、算数运算符 1、赋值符号 //把右侧的值赋给左侧的变量2、算数运算符 _ * / float f 1 / 2f; %3、算数运算符的优先级 //乘除余优先级高于加减 括号可以改变优先级&#xff0c;优先计算括号内的内容4、算数运算符的复合运算 复合运算符是用于自己 自己进行运算…

源码解读——SplitFed: When Federated Learning Meets Split Learning

源码地址 1. 源码概述 源码里一共包含了5个py文件 单机模型&#xff08;Normal_ResNet_HAM10000.py&#xff09;联邦模型&#xff08;FL_ResNet_HAM10000.py&#xff09;本地模拟的SFLV1&#xff08;SFLV1_ResNet_HAM10000.py&#xff09;网络socket下的SFLV2&#xff08;SF…

51单片机入门_江协科技_33~34_OB记录的自学笔记_LED呼吸灯与PWM直流马达调速

33. 直流电机驱动(PWM) 33.1. 直流电机介绍 •直流电机是一种将电能转换为机械能的装置。一般的直流电机有两个电极&#xff0c;当电极正接时&#xff0c;电机正转&#xff0c;当电极反接时&#xff0c;电机反转 •直流电机主要由永磁体&#xff08;定子&#xff09;、线圈&…

MySQL 死锁案例解析一则

原文链接&#xff1a;https://www.modb.pro/db/448666 一、问题背景某业务模块反馈数据库最近出现过几次死锁告警的情况&#xff0c;本文总结了这次死锁排查的全过程&#xff0c;并分析了导致死锁的原因及解决方案。希望给大家提供一个死锁的排查及解决思路。基础环境&#xff…

一.NODE MCU(ESP8285,ESP8286)开发环境搭建

一.序言: 1.esp8285长什么样? 2.esp8285是什么,能做什么? 通过上面图片,看到上面的芯片,是带有多个阵脚的单片机。实际上,看着该芯片很小,但是却具有完整的wifi无线蓝牙功能,它本身可以运行一个极简的linux小系统,并且该极简的小linux系统具备无线蓝牙功能。。它同…

54岁前港姐与好友因一事反目成仇,20年后方破冰

现年54岁的前「金牌司仪」陈淽菁&#xff08;前名&#xff1a;陈芷菁&#xff09;是1994年落选港姐&#xff0c;之后加入TVB参演电视剧《天地男儿》、《壹号皇庭》入屋&#xff0c;后因口齿伶俐而转战主持界。2017年陈淽菁离巢&#xff0c;外出以个人名义成立「陈芷菁工作室」&…

每日学习笔记:C++ STL算法之容器元素转换、结合、互换

本文API 转换元素 transform(sourceBeg,sourceEnd,destBeg, op) 结合元素 transform(source1Beg,source1End,source2Beg,destBeg, op) 互换元素 swap_ranges(sourceBeg,sourceEnd,destBeg) 转换元素 结合元素 互换元素

深度学习驱动的流体力学计算与应用

在深度学习与流体力学深度融合的背景下&#xff0c;科研边界不断拓展&#xff0c;创新成果层出不穷。从物理模型融合到复杂流动模拟&#xff0c;从数据驱动研究到流场智能分析&#xff0c;深度学习正以前所未有的力量重塑流体力学领域。近期在Nature和Science杂志上发表的深度学…

ARM_day8:温湿度数据采集应用

1、IIC通信过程 主机发送起始信号、主机发送8位(7位从机地址1位传送方向(0W&#xff0c;1R))、从机应答、发数据、应答、数据传输完&#xff0c;主机发送停止信号 2、起始信号和终止信号 SCL时钟线&#xff0c;SDA数据线 SCL高电平&#xff0c;SDA由高到低——起始信号 SC…