【js】对象属性的拦截和Proxy代理与Reflect映射的用法与区别

news/2025/1/15 14:07:48/

csdn动态图标

✍️ 作者简介: 前端新手学习中。

💂 作者主页: 作者主页查看更多前端教学

🎓 专栏分享:css重难点教学   Node.js教学 从头开始学习   ajax学习

文章目录

  • 对象属性的拦截
    • 介绍
    • Set
    • Get
  • 对象的拦截
    • 介绍
    • 使用
    • 对象属性拦截和对象拦截区别
    • 练习题
  • 映射
    • 介绍
    • 优点
  • 总结

对象属性的拦截

介绍

在对象中,set 和 get 是属性的特性,用于定义属性的赋值和取值行为。它们允许您在属性被赋值或取值时执行自定义的逻辑。

Set

set 是一个对象属性的特性,用于定义属性的赋值行为。当给属性赋值时,set 方法会被调用,允许执行自定义的逻辑。

  let obj = {name:0,set changename(value){if (value >5) {this.name =value;}}}
obj.changename=10  //10
obj.changename=4    //0
console.log(obj.name);

通过changename函数 在里面进行需要的条件判断来修改name值,给这个函数赋值的时候,就会触发这个set。
注意 函数名跟属性名不能一样,不然就要递归调用报栈溢出错误了,

Get

get 用于定义对象属性的获取行为。当访问对象的属性时,get 方法会被触发,并且可以在方法中执行相应的逻辑。

let obj = {name:0,set changename(value){if (value >5) {this.name =value;}},get changename(){return this.name =1},}
obj.changename=10  //10
obj.changename=4    //0
console.log(obj.changename); //1  (获取的时候会触发get)

假设 我们要访问一个属性,然后不管设置还有获取都需要对这个属性进行相应操作 ,我们就可以使用 很好的搭配使用set和get。 其实就相当于你针对一个属性写了两个不同的函数进行操作,只不过 set get 我们写的函数名称一样,便于易读浏览。

对象的拦截

介绍

Proxy 是 JavaScript 提供的一个内置对象,用于创建一个代理对象,可以拦截并自定义对目标对象的操作。通过使用 Proxy,我们可以对目标对象的属性访问、赋值、删除等操作进行拦截和处理。

使用

   let obj = {name: 0,};let handle = {set: function (target, name, value) {if (value > 5) {target[name] = value;}},get: function (target, name) {return (target[name] = 1);},};let proxy = new Proxy(obj, handle);proxy.changename = 10; //10proxy.changename = 4; //0console.log(proxy.changename); //1

通过proxy代理来访问 对象进行获取和赋值等操作。

对象属性拦截和对象拦截区别

区别就跟名字一样,对象属性拦截,是你在对象中给某个属性设置拦截操作,当它获取,和赋值的时候触发,对象拦截 是设置proxy代理,通过代理来访问,既然通过代理来访问对象属性,则任何操作,只要你对这个对象有操作,都会进行拦截判断,
也就是说 一个是针对对象里的一个属性,一个是针对整个对象。

练习题

   let obj = {name: 0,set changename(value) {if (value > 5) {this.name = value;}},get changename() {return (this.name += 1);},};let handle = {//target原对象,name是属性get: function (target, name) {target[name] += 1;//注意 get 一定要returnreturn target[name];},//value传的值set: function (target, name, value) {if (typeof value == "number") {target[name] = value;}},};let proxy = new Proxy(obj, handle);proxy.changename = 10;proxy.changename = "4";console.log(proxy.changename); 

写了个题目 供大家练习,感觉有面试题那味儿了,大家看看自己得出的结果是多少。

揭晓答案: 13。
讲解:proxy.changename = 10; 走proxy里的set, set里进行判断是一个数值,然后调用obj对象进行赋值,赋值的时候会触发obj的set拦截,判断大于5,ok最后赋值成10.
第二次 赋值字符串4 set判断 不通过就没下文了,默认return 一个undefined。
然后就是最后的显示了,显示的时候会触发proxy里的get 然后执行这段代码

 target[name] += 1;

也就是

target[name] =target[name] +1;

target[name] +1里的target[name] ,就相当于get操作触发obj里的get,于是就会加一,10+1变成了11,然后是11加1。也就是十二。
然后return target[name]; 又试一次get 操作 就是12 +1 结果就变成了 13。

映射

介绍

Reflect 是一个内置的 JavaScript 对象,它提供了一组用于操作对象的方法。这些方法与对象的操作行为相对应,例如属性访问、函数调用、实例化等。
通俗来讲,我们可以使用这个对象,来进行日常的对象操作,比如取值,赋值等等一些操作,他同样可以完成并且有一些其他的优点,我们使用reflect一般都是搭配proxy使用。

比如像下面这样。

const obj = {foo: 42,
};const value = Reflect.get(obj, 'foo');
console.log(value); // 输出: 42

优点

  1. 方便处理和调用目标对象的默认行为:Reflect 提供了与目标对象的默认行为相对应的方法,比如 Reflect.get、Reflect.set、Reflect.has 等。在 Proxy 的处理程序中使用 Reflect 可以方便地调用这些方法,从而实现对目标对象默认行为的处理和拦截。

  2. 更严谨的错误处理:Reflect 方法的返回值会更加准确地反映操作的结果,而不是像在使用目标对象的方法时可能会抛出异常。例如,Reflect.set 方法在赋值操作成功时会返回 true,失败时会返回 false,而不是抛出异常。

  3. 保持 Proxy 和目标对象的行为一致:Proxy 的目标对象可能是任意类型的对象,而 Reflect 提供了一致的方法,可以在 Proxy 的处理程序中对不同类型的目标对象进行操作,保持行为的一致性。

  4. 更清晰的代码逻辑:使用 Reflect 方法可以使代码更加简洁和易读,因为 Reflect 方法的命名和用法更加一致和直观,能够更清晰地表达代码的意图。

把它应用到我们上面的题。

 let obj = {name: 0,set changename(value) {if (value > 5) {this.name = value;}},get changename() {return (this.name += 1);},};let handle = {//target原对象,name是属性get: function (target, name) {target[name] += 1;//注意 get 一定要returnreturn Reflect.get(target, name);},//value传的值set: function (target, name, value) {if (typeof value == "number") {Reflect.set(target, name, value)}},};let proxy = new Proxy(obj, handle);proxy.changename = 10;proxy.changename = "4";console.log(proxy.changename);···

总结

  1. 对象属性的拦截(Object Property Interception):可以使用对象自身的 get 和 set 方法来拦截属性的获取和设置操作。通过在对象上定义这些方法,可以在属性访问过程中执行自定义的逻辑,例如验证、转换或拦截。

  2. 代理对象(Proxy Object):代理对象是一个代理目标对象的对象,通过代理对象可以拦截对目标对象的操作。代理对象使用 Proxy 构造函数创建,并提供了一组拦截器(handler)来定义拦截行为。

  3. Reflect 映射(Reflect Mapping):Reflect 是一个内置的对象,提供了一组与对象操作相关的方法,用于执行与目标对象相同的操作。Reflect 方法提供了一种更简洁、易读的方式来执行常见的对象操作,如获取属性值、设置属性值、调用函数等。


http://www.ppmy.cn/news/98516.html

相关文章

Etcdctl 命令v3

一、v3必须导出环境变量 export ETCDCTL_API3 二、查看版本 etcdctl version 三、写入键 1.基本 etcdctl put foo bar 2.绑定租约 etcdctl put foo bar --leasexxxx 四、获取键 1.基本 etcdctl get foo 2.按十六进制获取 etcdctl get foo --hex 3.只读取键值 et…

Spring高手之路——深入理解与实现IOC依赖查找与依赖注入

本文从xml开始讲解,注解后面给出 文章目录 1. 一个最基本的 IOC 依赖查找实例2. IOC 的两种实现方式2.1 依赖查找(Dependency Lookup)2.2 依赖注入(Dependency Injection) 3. 在三层架构中的 service 层与 dao 层体会依…

数字信号处理8:利用Python进行数字信号处理基础

我前两天买了本MATLAB信号处理,但是很无语,感觉自己对MATLAB的语法很陌生,看了半天也觉得自己写不出来,所以就对着MATLAB自己去写用Python进行的数字信号处理基础,我写了两天左右,基本上把matlab书上的代码…

​【编写UI自动化测试集】Appium+Python+Unittest+HTMLRunner​

简介 获取AppPackage和AppActivity 定位UI控件的工具 脚本结构 PageObject分层管理 HTMLTestRunner生成测试报告 启动appium server服务 以python文件模式执行脚本生成测试报告 下载与安装 下载需要自动化测试的App并安装到手机 获取AppPackage和AppActivity 方法一 有源码的…

MySQL:查询时进行时间比较

MySQL:查询时进行时间比较 前言一、查询距离当前时间多久以前二、查询特定时间范围 前言 在 MySQL 中查数据的时候,往往需要对记录的创建时间进行筛选,比如只需要查询今年1-5月份的,或者查询距离当前时间多久以前的。 本文介绍了…

C++ QT QSerialPort基操

以下是使用QSerialPort的基本步骤&#xff1a;1. 引入QSerialPort头文件 #include <QSerialPort>2. 创建QSerialPort对象 QSerialPort serialPort;3. 设置串口参数 serialPort.setPortName("COM1"); // 设置串口名称 serialPort.setBaudRate(QSerialPort::Baud…

DAY 67 redis高可用之持久化

Redis 高可用 什么是高可用 在web服务器中&#xff0c;高可用是指服务器可以正常访问的时间&#xff0c;衡量的标准是在多长时间内可以提供正常服务(99.9%、99.99%、99.999%等等)。 但是在Redis语境中&#xff0c;高可用的含义似乎要宽泛一些&#xff0c;除了保证提供正常服…

C++ Primer第五版_第十九章习题答案(11~20)

文章目录 练习19.11练习19.12练习19.13练习19.14练习19.15练习19.16练习19.17练习19.18练习19.19练习19.20 练习19.11 普通的数据指针和指向数据成员的指针有何区别&#xff1f; 普通的数据指针指向一个对象&#xff1b;类成员指针指向类的非静态成员。当初始化这样一个指针时&…