什么是proxy代理?

1. 什么是proxy代理

代理(Proxy)是 JavaScript 中一种非常强大而灵活的功能。代理允许你拦截并覆盖对象的默认行为,提供了一种拦截、定制和扩展对象操作的机制。

简单说,就是在访问对象属性或者赋值时,可以做一些额外的操作。

代理通过使用 Proxy 对象来创建。
Proxy 接受两个参数:目标对象(被代理的对象)和一个处理程序对象(handler)。处理程序对象又分为了get()捕获器set()捕获器

先看一个简单的栗子,创建一个空代理,不会做任何的额外操作。

        const target = {msg: 'hello'};const handler = {};const proxy = new Proxy(target, handler);//属性会访问同一个值console.log(target.msg)//helloconsole.log(proxy.msg)//hellotarget.msg = 'morning';console.log(target.msg)//morningconsole.log(proxy.msg)//morning// 严格相等可以用来区分代理对象和目标对象console.log(target === proxy); // false 

要想定义额外的操作,要在handler中定义捕获器。通过代理对象访问属性,会触发get()捕获器; 通过代理对象给属性赋值。会触发set()捕获器。

        const John = {name: 'John',age: 20};const handler = {// 这里就额外输出了属性名get: function (target, property, receiver) {console.log(`property: ${property}`);return Reflect.get(target, property, receiver);//获取对象的属性值},set: function (target, property, value, receiver) {if (property === 'age') {if (value < 18) {throw new Error('年龄必须大于等于 18');}}return Reflect.set(target, property, value, receiver);//设置对象的属性}}const proxy = new Proxy(John, handler);// 直接通过对象访问属性,不会触发代理的 get 捕获器console.log(John.name); // 输出 'John'// 通过代理对象访问属性,会触发代理的 get 捕获器console.log(proxy.name); // 输出 'property: name' 和 'John'proxy.age = 23;console.log(proxy.age);//输出 'property: age' 和 23proxy.age = 16;//Uncaught Error: 年龄必须大于等于 18

2. Reflect.get()

在JavaScript中,我们通常通过点符号(obj.property)或方括号(obj['property'])来访问对象的属性。而 Reflect.get() 也是获取对象的属性值。

Reflect.get(target, propertyKey, receiver)

  • target:目标对象,即从这个对象中获取属性值。
  • propertyKey:属性键,即要获取的属性的键名。
  • receiver:可选,如果提供,那么 receiver 将作为 this 值传递给目标对象的 getter 方法。如果省略,将使用 target 作为 this 值。
const person = { name: 'John', age: 30 };// 通过点符号
const name1 = person.name;// 通过方括号
const name2 = person['name'];//使用 Reflect.get 获取属性值
const name3 = Reflect.get(person, 'name');

3. Reflect.get()与常见获取对象属性值有什么不同?

相同点:当访问不存在属性时都会返回undefined

const person = { age: 30 };console.log(person.name);                  // 输出 undefined
console.log(Reflect.get(person, 'name'));  // 输出 undefined

不同点:Reflect.get()触发代理的捕获器,而用点符号、方括号去访问不会。

        const person = { age: 30 };const handler = {get: function (target, property) {console.log(`property: ${property}`);return Reflect.get(target, property);}};console.log(Reflect.get(person, 'name'));  // 输出 "property: name",并且返回 undefinedconsole.log(person.name);                  // 输出 undefined

4. proxy代理的应用

1. 拦截和定制对象操作

通过代理,你可以使用捕获器(例如 getsetapply 等)来拦截和定制对象上的操作。也就是在操作执行前后执行自定义逻辑,比如记录日志、验证数据、实现观察者模式等。

const handler = {get: function(target, property, receiver) {console.log(`Getting property: ${property}`);return Reflect.get(target, property, receiver);},set: function(target, property, value, receiver) {console.log(`Setting property: ${property} to ${value}`);return Reflect.set(target, property, value, receiver);}
};const proxy = new Proxy({}, handler);
proxy.name = 'John'; // 输出 "Setting property: name to John"
console.log(proxy.name); // 输出 "Getting property: name" 和 "John"

2. 数据验证和保护

通过代理,可以实现对对象属性的更严格的验证,以确保数据的完整性和安全性。

const validator = {set: function(target, prop, value) {if (prop === 'age' && (typeof value !== 'number' || value <= 0)) {throw new Error('请输入正确的年龄!');}return Reflect.set(target, prop, value);}
};const person = new Proxy({}, validator);
person.age = 30; // 设置成功
person.age = 'thirty'; // 抛出错误:请输入正确的年龄!

3. 观察者模式

通过代理,可以实现观察者模式,即对对象的变化进行监听,并在变化发生时执行相应的操作

function createObservable(obj, onChange) {return new Proxy(obj, {set: function(target, prop, value, receiver) {onChange(prop, value);return Reflect.set(target, prop, value, receiver);}});
}const user = { name: 'John', age: 30 };
const observedUser = createObservable(user, (prop, value) => {console.log(`Property ${prop} changed to ${value}`);
});observedUser.age = 31; // 输出 "Property age changed to 31"

4. 动态属性生成

通过代理,可以动态生成属性的值,而不是静态地存储它们。

const dynamicProperties = new Proxy({}, {get: function(target, prop, receiver) {if (!(prop in target)) {target[prop] = `Dynamic value for ${prop}`;}return Reflect.get(target, prop, receiver);}
});console.log(dynamicProperties.name); // 输出 "Dynamic value for name"

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

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

相关文章

引用、动态内存分配、函数、结构体

引用 定义和初始化 **数据类型 &引用名 目标名;**引用和目标共用同一片空间&#xff08;相当于对一片空间取别名&#xff09;。 引用的底层实现&#xff1a;数据类型 * const p&#xff1b; ------> 常指针 int const *p; -----> 修饰 *p const int *p; ----->…

第六题-红和蓝【第六届传智杯程序设计挑战赛解题分析详解复盘】(JavaPythonC++实现)

🚀 欢迎来到 ACM 算法题库专栏 🚀 在ACM算法题库专栏,热情推崇算法之美,精心整理了各类比赛题目的详细解法,包括但不限于ICPC、CCPC、蓝桥杯、LeetCode周赛、传智杯等等。无论您是刚刚踏入算法领域,还是经验丰富的竞赛选手,这里都是提升技能和知识的理想之地。 ✨ 经典…

stm32实现0.96oled图片显示,菜单功能

stm32实现0.96oled图片显示&#xff0c;菜单功能 功能展示简介代码介绍oled.coled.holedfont.h&#xff08;字库文件&#xff09;main函数 代码思路讲解 本期内容&#xff0c;我们将学习0.96寸oled的进阶使用&#xff0c;展示图片&#xff0c;实现菜单切换等功能&#xff0c;关…

QT visual stdio加载动态库报错126问题

报错126是找不到指定的模块 QT 查看构建目录&#xff0c;将依赖的动态库放到该目录下即可成功 visual stdio将依赖的动态库放到运行目录 在vs中使用导出类的动态库时&#xff0c;不但需要将对应的.dll放到对应的目录下&#xff0c;还需要将该动态库对应的.lib添加到如下配置才…

【SAS Planet 下载地图瓦片】

SAS Planet是一位俄罗斯爱好者创建的的开源应用&#xff0c;该应用可以浏览与下载主流网络地图&#xff0c;包括Google地图、Google地球、Bing地图、Esri 地图、Yandex地图等&#xff0c;支持100多图源。 安装包下载地址&#xff1a;https://www.sasgis.org/download/ github…

337. 打家劫舍III (二叉树)

题目 题解 # Definition for a binary tree node. # class TreeNode: # def __init__(self, val0, leftNone, rightNone): # self.val val # self.left left # self.right right class Solution:def rob(self, root: Optional[TreeNode]) ->…

指针的进阶

重中之重&#xff1a; 目录 1.字符指针&#xff1a; 2.指针数组 3.数组指针 4.数组参数、指针参数 5.函数指针 1.字符指针&#xff1a; 一般实现&#xff1a; int main() {char ch w;char *pc &ch;*pc w;return 0; } 二班实现&#xff1a; int main() {const c…

第一题-字符串拼接【第六届传智杯程序设计挑战赛解题分析详解复盘】(C/C++实现)

🚀 欢迎来到 ACM 算法题库专栏 🚀 在ACM算法题库专栏,热情推崇算法之美,精心整理了各类比赛题目的详细解法,包括但不限于ICPC、CCPC、蓝桥杯、LeetCode周赛、传智杯等等。无论您是刚刚踏入算法领域,还是经验丰富的竞赛选手,这里都是提升技能和知识的理想之地。 ✨ 经典…

CSS3媒体查询实现不同宽度的下不同内容的展示

文章目录 前言CSS3 多媒体查询实例520 到 699px 宽度 - 添加邮箱图标700 到 1000px - 添加文本前缀信息大于 1001px 宽度 - 添加邮件地址大于 1151px 宽度 - 添加图标代码后言 前言 hello world欢迎来到前端的新世界 &#x1f61c;当前文章系列专栏&#xff1a;CSS &#x1f43…

什么是闭包和作用域链?

1. 什么是闭包 闭包指的是那些引用了另一个函数作用域中变量的函数&#xff0c;通常是在嵌套函数中实现的。 举个栗子&#xff0c;createCounter 接受一个参数 n&#xff0c;然后返回一个匿名函数&#xff0c;这个匿名函数是闭包&#xff0c;它可以访问外部函数 createCounte…

智能优化算法应用:基于鲸鱼算法无线传感器网络(WSN)覆盖优化 - 附代码

智能优化算法应用&#xff1a;基于鲸鱼算法无线传感器网络(WSN)覆盖优化 - 附代码 文章目录 智能优化算法应用&#xff1a;基于鲸鱼算法无线传感器网络(WSN)覆盖优化 - 附代码1.无线传感网络节点模型2.覆盖数学模型及分析3.鲸鱼算法4.实验参数设定5.算法结果6.参考文献7.MATLAB…

Nginx常见的中间件漏洞

目录 1、Nginx文件名逻辑漏洞 2、Nginx解析漏洞 3、Nginx越权读取缓存漏洞 这里需要的漏洞环境可以看&#xff1a;Nginx 配置错误导致的漏洞-CSDN博客 1、Nginx文件名逻辑漏洞 该漏洞利用条件有两个&#xff1a; Nginx 0.8.41 ~ 1.4.3 / 1.5.0 ~ 1.5.7 php-fpm.conf中的s…

基于单片机的温湿度检测系统设计

目录 摘 要... 2 第一章 绪论... 5 1.1 研究课题背景... 5 1.2 国内外发展概况... 7 1.3 课题研究的目的... 8 1.4 课题的研究内容及章节安排... 8 第二章 温湿度检测系统控制系统的设计方案... 10 2.1 设计任务及要求... 10 2.2 温湿度检测系统总体设计方…

百度 Comate 终于支持 IntelliJ IDEA 了

大家好&#xff0c;我是伍六七。 对于一直关注 AI 编程的阿七来说&#xff0c;编程助手绝对是必不可少的&#xff0c;除了 GitHub Copilot 之外&#xff0c;国内百度的 Comate 一直是我关注的重点。 但是之前&#xff0c;Comate 还支持 VS code&#xff0c;并不支持 IntelliJ…

mybatis的使用,mybatis的实现原理,mybatis的优缺点,MyBatis缓存,MyBatis运行的原理,MyBatis的编写方式

文章目录 MyBatis简介结构图Mybatis缓存&#xff08;一级缓存、二级缓存&#xff09;MyBatis是什么&#xff1f;mybatis的实现原理JDBC编程有哪些不足之处&#xff0c;MyBatis是如何解决这些问题的&#xff1f;Mybatis优缺点优点缺点映射关系 MyBatis的解析和运行原理MyBatis的…

【单片机学习笔记】STC8H1K08参考手册学习笔记

STC8H1K08参考手册学习笔记 STC8H系列芯片STC8H1K08开发环境串口烧录 STC8H系列芯片 STC8H 系列单片机是不需要外部晶振和外部复位的单片机&#xff0c;是以超强抗干扰/超低价/高速/低功耗为目标的 8051 单片机,在相同的工作频率下,STC8H 系列单片机比传统的 8051约快12 倍速度…

数组题目:645. 错误的集合、 697. 数组的度、 448. 找到所有数组中消失的数字、442. 数组中重复的数据 、41. 缺失的第一个正数

645. 错误的集合 思路&#xff1a; 我们定义一个数组cnt&#xff0c;记录每个数出现的次数。然后我们遍历数组&#xff0c;从1开始&#xff0c;如果cnt[i] 0 那就说明这个是错误的数&#xff0c;如果 cnt[i] 2&#xff0c;那就说明是重复的数。 代码&#xff1a; class So…

RabbitMQ之消费者可靠性

文章目录 前言一、消费者确认机制二、失败重试机制三、失败处理策略四、业务幂等性唯一消息ID业务判断 五、兜底方案总结 前言 当RabbitMQ向消费者投递消息以后&#xff0c;需要知道消费者的处理状态如何。因为消息投递给消费者并不代表就一定被正确消费了&#xff0c;可能出现…

WSL开发环境配置指南

WSL开发环境配置指南 WSL 安装 Ubuntu20.04 wsl --list --online 查看能够使用的linux发行版wsl --install Ubuntu-20.04 安装Ubuntu2004发行版wsl --shutdown Ubuntu-20.04 关闭Ubuntu2004发行版wsl --export Ubuntu-20.04 W:\Linux\Ubuntu\Ubuntu-20.04\Ubuntu2004.tar 将Ubu…

3DMAX平滑布尔插件超级布尔工具使用教程

3dMax平滑布尔插件SmoothBoolean用于在ProBoolean网格之间创建平滑过渡的3dMax插件。再也不需要花几个小时来清理用布尔切割创建的混乱拓扑了。如果你只是想让你的三维模型在渲染图上看起来很棒&#xff0c;或者你需要为游戏烘焙一些东西&#xff0c;那么你就不必浪费时间来建模…