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 的绑定取决于 Proxy 的 get 捕获器中 Reflect.get 的第三个参数 receiver。

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

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

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

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

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

在 Proxy 的 get 陷阱中,使用 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 进行,而不会再次触发 Proxy 的 get 陷阱。因此,this._age 的访问不会被拦截。

相反,当你使用 Reflect.get(target, property, receiver) 时,你提供了另一个对象作为 receiver。这通常会是 Proxy 对象本身(即 userProxy)。在这种情况下,如果属性是一个 getter 方法,并且这个方法内部使用 this 来访问其他属性,那么这些访问将会通过 Proxy 的 get 陷阱进行。这是因为 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 age 和 Intercepted access to _age。

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

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈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行业内整体的人才…

Linux hwclock命令教程:管理和操作硬件时钟(附实例详解和注意事项)

Linux modinfo命令介绍 modinfo(模块信息)命令在Linux系统中用于显示Linux内核模块的信息。此命令从命令行给出的Linux内核模块中提取信息。如果模块名称不是文件名,则默认搜索/lib/modules/kernel-version目录。modinfo可以理解来自任何Lin…

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;我为了快点实现能提交后在当前页面获得判…

Linux: security: sudo 的一个隐藏问题

说这个隐藏是根据一般的知识&#xff0c;肯定是想不到它会读取本机的ip地址和mask。 这个命令在执行的时候会读取本地地址列表。是下面这个commit引进来的一个plugin https://github.com/sudo-project/sudo/commit/1009d7a3e6ed2b7811473c91d90082cfe4dd2db9 /* Load local IP…

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

通过上一篇文章&#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、算数运算符的复合运算 复合运算符是用于自己 自己进行运算…

2024-04-17 学习笔记(李宏毅AI基础课,图像预处理)

1.Hung-yi Lee 摘要&#xff1a;这篇文章介绍了李宏毅教授的课程内容和作业安排&#xff0c;涵盖了深度学习的理论、优化、泛化、特殊网络结构、特殊训练技术、生成对抗网络(GAN)以及深度强化学习等主题。 Raiden说&#xff1a;基础知识&#xff0c;常学常新 2.软包装锂离子电…

源码解读——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;、线圈&…

笔记本触摸板的使用

使用电脑很多面年了&#xff0c;但很少使用触摸板&#xff0c;最近公司配置了台新笔记本触摸板很丝滑&#xff0c;像着改变一下多年使用电脑的习惯&#xff0c;做个笔记&#xff0c;使用它&#xff0c;适应它&#xff01; 单手指&#xff1a; 单击→左键 两次单击→打开文件夹&…

MySQL 死锁案例解析一则

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

绩效考核管理:激发潜力,实现双赢

绩效考核管理是现代企业管理中不可或缺的一环&#xff0c;它不仅关乎员工的个人发展&#xff0c;更影响着企业的整体战略目标实现。本文将从绩效考核管理的意义、目标设定、考核方法、激励措施以及持续改进等方面展开论述&#xff0c;探讨如何通过有效的绩效考核管理激发员工潜…