js语法---理解反射Reflect对象和代理Proxy对象

Reflect

基本要点

        反射:reflect是一个内置的全局对象,它的作用就是提供了一些对象实例的拦截方法,它的用法和Math对象相似,都只有静态方法和属性,同时reflect也没有构造器,无法通过new运算符构建实例对象(无实例的全局对象);也就是说reflect相当于一个工具类,只对外提供方法进行使用。

tips 拦截方法:拦截方法是指,通过自身方法去覆盖掉原有的默认方法,这样就只会生效拦截方法的操作,而不执行默认操作(例如,setter的作用,覆盖了原有的赋值操作),

这里使用了reflect的方法就不需要再使用默认的方法了

运用示例

以下使用几个简单的reflect的对比示例

Reflect.ownKeys()

获取对象的所有属性(不限于字符串),返回一个数组 ,作用类似Object.keys

Reflect.ownKeys(target)target:获取自身属性键的目标对象。
let obj ={content: 'hello world',length: 11,char: 'utf-8'
}let Keys = Object.keys(obj) // 返回一个由属性名组成的数组
console.log(Keys); // ['content', 'length', 'char']let keys = Reflect.ownKeys(obj) // 返回一个由属性名组成的数组
console.log(keys); // ['content', 'length', 'char']

         这两个方法的效果一致都能拿到对象所有的属性名,但是Object.keys只能得到对象属性的字符串值,如果一个对象的属性包含symbol类型,就无法将其正确的识别出来,而Reflect.ownKeys就可以做到。

关于symbol类型可以参考:js基本类型---symbol标识符_js symbol属于什么类型-CSDN博客

 

Reflect.has()

判定对象中是否存在某个属性,与 in 操作符 相同,返回Boolean值。

let isChar = Reflect.has(obj, 'char') // 判断属性是否存在
console.log(isChar); // true

 Reflect.get()

返回对象(数组)中指定属性的值

Reflect.get(target, propertyKey[, receiver])// target 需要取值的目标对象// propertyKey 需要获取的值的键值// receiver 如果target对象中指定了getter,receiver则为getter调用时的this值。
let content = Reflect.get(obj, 'content') // 获取属性值
console.log(content); // hello world

 

Reflect.set()

静态方法 Reflect.set() 在一个对象上设置一个属性的值,返回Boolean值

Reflect.set(target, propertyKey, value)
Reflect.set(target, propertyKey, value, receiver)//target 设置属性的目标对象。//propertyKey 设置的属性的名称。//value 设置的值。// receiver 如果遇到 setter,receiver则为setter调用时的this值。
// obj.content = '你好,世界' // 设置属性值let setContent = Reflect.set(obj, 'content', '你好,世界') // 设置属性值
console.log(setContent); // true,成功时返回true,否则返回false
console.log(Reflect.get(obj, 'content') ); // 你好,世界
console.log(obj.content); // 你好,世界

 

Reflect.deleteProperty()

静态方法 Reflect.deleteProperty() 允许用于删除属性。它很像delete obj.key,但它是一个函数,成功时返回true,否则返回false,这里的成功是根据结果来看的,如果属性不存在,则返回true,否则返回false

Reflect.deleteProperty(target, propertyKey)// target 删除属性的目标对象。// propertyKey 需要删除的属性的名称。

 

delete obj.content // 删除属性
console.log(obj); // {length: 11, char: 'utf-8'}let deleteContent = Reflect.deleteProperty(obj, 'content') // 删除属性
console.log(deleteContent); // true,成功时返回true,否则返回false,这里的成功是根据结果来看的,如果属性存在,则返回true,否则返回false
console.log(obj); // {length: 11, char: 'utf-8'}
console.log(obj);

为什么使用reflect

Reflect 提供的是一整套反射能力 API,它的调用方式,参数和返回值都是统一风格的,在Reflect 出现之前我们只是利用分散的 API 完成一些动态编程的事情,让动态编程有了一个统一的使用标准

和proxy的关系

proxy是代理对象,它的构造器中就包含了和Reflect相同的方法,当使用proxy代理一个引用类型时,就可以简洁的使用Reflect来实现动态编程的效果,

Reflect和proxy的切合度很高,同时也能够避免使用过多分散API带来的隐性错误(如receiver可以解决this的指向问题)和代码的冗余

总之,reflect整合了一套API用于动态化编程,它可以方便简洁的实现proxy的动态拦截代理

tips 动态编程:响应式数据的原理,当修改页面上的某一个值时,页面效果也随之改变

Proxy

Proxy 对象用于创建一个对象的代理,从而实现基本操作的拦截和自定义(如属性查找、赋值、枚举、函数调用等)。

构造器

const p = new Proxy(target, handler)// target 要使用 Proxy 包装的目标对象(可以是任何类型的对象,包括原生数组,函数,甚至另一个代理)。// handler 一个通常以函数作为属性的对象,各属性中的函数分别定义了在执行各种操作时代理 p 的行为,比如访问和赋值时的而外操作。

Proxy.revocable()

Proxy.revocable() 方法可以用来创建一个可撤销的代理对象。返回一个包含了代理对象本身和它的撤销方法的可撤销 Proxy 对象。

Proxy.revocable(target, handler);
// target 将用 Proxy 封装的目标对象。可以是任何类型的对象,包括原生数组,函数,甚至可以是另外一个代理对象。// handler 一个对象,其属性是一批可选的函数,这些函数定义了对应的操作被执行时代理的行为。

代理的意义

        首先代理的对象和原对象的属性和值是绑定一致的,可以理解为指向同一个内存地址,也就是说对代理对象的所有操作结果,最终都会回到原对象中,这个过程就可以实现一些其他操作,例如,改变一个对象的值时,将页面重载一遍,引起页面的变化,这个过程就是响应

一个proxy示例


let obj = {name: '张三',age: 20,sex: '男',/*** @param {any} val*/set address(val){this.address = val;return val;}
}const p = new Proxy(obj,{get: (obj,key,receiver)=>{let res = Reflect.get(obj,key,receiver);return res;},set: (obj,key,val,receiver)=>{if(typeof val == 'number'){console.log('不能设置数字')return;}let res = Reflect.set(obj,key,val,receiver);return res;}
})
p.name='李四';
p.age=18;
console.log(obj,p)

可以看到 被代理的对象obj会受到p的影响触发改变,而对代理对象属性赋值时,我们可以在中间穿插其他操作,如这里不允许对属性赋值数字,

完整代码和结果展示

reflect.js

let obj ={content: 'hello world',length: 11,char: 'utf-8'
}let Keys = Object.keys(obj) // 返回一个由属性名组成的数组
console.log(Keys); // ['content', 'length', 'char']let keys = Reflect.ownKeys(obj) // 返回一个由属性名组成的数组
console.log(keys); // ['content', 'length', 'char']let isChar = Reflect.has(obj, 'char') // 判断属性是否存在
console.log(isChar); // truelet content = Reflect.get(obj, 'content') // 获取属性值
console.log(content); // hello world
console.log(obj.content); // hello world// obj.content = '你好,世界' // 设置属性值let setContent = Reflect.set(obj, 'content', '你好,世界') // 设置属性值
console.log(setContent); // true,成功时返回true,否则返回false
console.log(Reflect.get(obj, 'content') ); // 你好,世界
console.log(obj.content); // 你好,世界delete obj.content // 删除属性
console.log(obj); // {length: 11, char: 'utf-8'}let deleteContent = Reflect.deleteProperty(obj, 'content') // 删除属性
console.log(deleteContent); // true,成功时返回true,否则返回false,这里的成功是根据结果来看的,如果属性存在,则返回true,否则返回false
console.log(obj); // {length: 11, char: 'utf-8'}
console.log(obj);

proxy.js 


let obj = {name: '张三',age: 20,sex: '男',/*** @param {any} val*/set address(val){this.address = val;return val;}
}const p = new Proxy(obj,{get: (obj,key,receiver)=>{let res = Reflect.get(obj,key,receiver);return res;},set: (obj,key,val,receiver)=>{if(typeof val == 'number'){console.log('不能设置数字')return;}let res = Reflect.set(obj,key,val,receiver);return res;}
})
p.name='李四';
p.age=18;
console.log(obj,p)

更多内容

更多Reflect和proxy相关的方法和属性可以查看:

Reflect - JavaScript | MDN (mozilla.org)

Proxy() 构造函数 - JavaScript | MDN (mozilla.org)

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

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

相关文章

WinRAR应用文件图标是白色怎么解决

1.打开程序-选项-设置 2.找到集成-选择全部切换,保存即可。

Mobvista汇量科技解析奥运机会点及营销理念,看广告投放如何抢占先机

四年一度的奥运盛会,作为少有能跨越文化、宗教、种族、行为等各方面差异的体育事件,更能广泛吸引全球观众的目光,成为品牌方和广告主天然的流量磁铁。应用增长平台Mobvista汇量科技为助力各行业开发者、各品牌商家抢占奥运流量,分…

【CT】LeetCode手撕—141. 环形链表

目录 题目1- 思路2- 实现⭐141. 环形链表——题解思路 3- ACM实现 题目 原题连接:141. 环形链表 1- 思路 模式识别 模式1:判断链表的环 ——> 快慢指针 思路 快指针 ——> 走两步慢指针 ——> 走一步判断环:若快慢相遇则有环&a…

北京银行品牌价值提升160亿元首破千亿 位居《中国500最具价值品牌》榜第85位!

6月19日,由世界品牌实验室(World Brand Lab)主办的第二十一届“世界品牌大会”在北京举行,活动现场发布了2024年《中国500最具价值品牌》榜单。在这份基于财务数据、品牌强度和消费者行为分析的年度报告中,北京银行最新品牌价值达1036.62亿元…

将Jar用三种方式生成Windows的安装程序

无论是WEB(spring boot)的JAR,还是JavaFX以及swing的Jar,要生成windows方式。 打包成Windows可执行文件(.exe),你可以使用以下三种方法: ### 方法1:使用Inno Setup 1. **构建JavaFX应用程序**: 使用M…

LaTeX 学习 第2节 数学结构

----用教授的方式学习 目录 2.1 上标与下标 2.2 上下画线与花括号 2.3 分式 2.4 根式 2.5 矩阵 ​​​​​​​LaTex安装包:https://download.csdn.net/download/weixin_38135241/89416392 LaTex- windows安装包:https://download.csdn.net/down…

web爬虫笔记:js逆向案例九(某多多 anti_content参数)补环境流程

web爬虫笔记:js逆向案例九(某多多 anti_content参数)补环境流程 一、目标网站:aHR0cHM6Ly9tb2JpbGUueWFuZ2tlZHVvLmNvbS8= 二、接口分析 1、快速定位加密位置(通过搜索/cells/hub/v3快速定位到加密js文件) 2、通过分析可知&#

springBoot多数据源使用、配置

又参加了一个新的项目,虽然是去年做的项目,拿来复用改造,但是也学到了很多。这个项目会用到其他项目的数据,如果调用他们的接口取数据,我还是觉得太麻烦了。打算直接配置多数据源。 然后去另一个数据库系统中取出数据…

王思聪隐形女儿曝光

王思聪"隐形"女儿曝光!黄一鸣独自面对怀孕风波,坚持生下爱情结晶近日,娱乐圈掀起了一场惊天波澜!前王思聪绯闻女友黄一鸣在接受专访时,大胆揭露了她与王思聪之间的爱恨纠葛,并首度公开承认&#…

kubernetes 核心概念

1 kubernetes核心概念 1.1 Pod Pod是可以在Kubernetes中创建和管理的、最小的可部署的计算单元。 Pod就像豌豆荚一样,其中包含着一组(一个或多个)容器;这些容器共享存储、网络、以及怎样运行这些容器的声明。 Pod就像一台物理…

Suno AI如何解决制作多语言混合的歌曲~

导读 你想不想制作一首有中文和粤语混合的歌曲? 你想不想制作一首有中文和日语混合的歌曲? 你想不想制作一首有中文和英语混合的歌曲? 如果你想不知道怎么操作,可以阅读下本文。 说明 本文让AI唱一首中文和日语混合的歌曲&am…

Linux笔记--vi编辑器

vi编辑器 基本操作 对于vi编辑器有这几种模式 移动 当编辑一个过大的文件时通过方向键移动光标过慢所以可以使用快捷键进行移动 编辑 dw指令只能在单词第一个字母处使用 D指令删除的是当前行 查找替换 pattern指代想要搜索的内容

Chrome插件开发入门:手把手教你创建第一个扩展

问题背景 最近,客户发布了一个新的任务 —— 开发一个Chrome插件。之前没有这方面的开发经验,准备想学习一下这块的内容,我发现网上的大多数视频都是几年前的,开发版本都是基于MV2,当前谷歌已经开始使用MV3&#xff0…

Elasticsearch如何聚合查询多个统计值,如何嵌套聚合?并相互引用,统计索引中某一个字段的空值率?语法是怎么样的

文章目录 Elasticsearch聚合查询说明空值率查询DSL Elasticsearch聚合基础知识扩展Elasticsearch聚合概念Script 用法Elasticsearch聚合查询语法指标聚合(Metric Aggregations)桶聚合(Bucket Aggregations)矩阵聚合(Ma…

代码随想录第28天|回溯算法

491. 非递减子序列 思路: 不可以排序, 否则会改变元素的顺序对收获的结果有要求, num.size() > 2, 且 num[i - 1] < num[i]需要进行去重, 不能使用排序后的方法去重每一层可用 unordered_set 去重组合问题, for 遍历需要标记起始位置 bug: 一定要先判断元素是否重复, …

RabbitMQ实践——在Ubuntu上安装并启用管理后台

大纲 环境安装启动管理后台 RabbitMQ是一款功能强大、灵活可靠的消息代理软件&#xff0c;为分布式系统中的通信问题提供了优秀的解决方案。无论是在大规模数据处理、实时分析还是微服务架构中&#xff0c;RabbitMQ都能发挥出色的性能&#xff0c;帮助开发者构建高效、稳定的系…

Microsoft AI Day:支持开放合作,普及技术应用,推进行业企业智慧化创新

微软在北京举办以“共创AI创新&#xff0c;智启无限可能”为主题的Microsoft AI Day活动&#xff0c;集中展示了在生成式智能技术加速发展普及的过程中&#xff0c;微软取得的最新技术突破与进展&#xff0c;并同步更新了在Microsoft Build 2024全球开发者大会上发布的一系列Az…

基于Java的高校校园点餐系统

开头语&#xff1a; 你好&#xff0c;我是计算机专业的学长&#xff0c;如果你对高校校园点餐系统感兴趣或有相关开发需求&#xff0c;欢迎联系我。 开发语言&#xff1a;Java 数据库&#xff1a;MySQL 技术&#xff1a;JSP技术 工具&#xff1a;Eclipse、Tomcat 系统展示…

安享智慧理财金融测试项目

1. 项目介绍 安享智慧理财金融系统是基于 Java 语言开发&#xff0c;集 PC 端、APP 端、WAP 端为一体的 P2P&#xff08;个人对个人&#xff09;的借贷系统&#xff0c;提供了完整的借款和投资功能。 web用户端 说明&#xff1a;PC 网站&#xff0c;供借款人和投资人使用功能…

PySide(PyQt)的特殊按钮(互锁、自锁、独占模式)

界面图: Qt Designer中创建窗口,放置一个QGroupBox,命名为btnStation,这就是自定义的按钮站,按钮站里放置6个按钮。自锁按钮相当于电器中的自锁功能的按钮,每按一次状态反转并保持不变。独占按钮也是自锁功能的按钮,不同的是当独占按钮为ON时,其余所有按钮均被置为OFF…