当前位置: 首页 > news >正文

什么是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"

相关文章:

什么是proxy代理?

1. 什么是proxy代理 代理&#xff08;Proxy&#xff09;是 JavaScript 中一种非常强大而灵活的功能。代理允许你拦截并覆盖对象的默认行为&#xff0c;提供了一种拦截、定制和扩展对象操作的机制。 简单说&#xff0c;就是在访问对象属性或者赋值时&#xff0c;可以做一些额外…...

opencv-python读取的图像分辨率太大不能完全显示

如果使用OpenCV-Python读取的图像分辨率太大&#xff0c;无法完全显示在屏幕上&#xff0c;可以考虑以下几种方法&#xff1a; 1.缩放图像&#xff1a;使用OpenCV的resize函数&#xff0c;将图像缩小到适合屏幕显示的大小。例如&#xff0c;可以将图像的宽度和高度都缩小到屏幕…...

【ArcGIS Pro微课1000例】0038:基于ArcGIS Pro的人口密度分析与制图

文章目录 一、人口密度二、人口密度分析1. 点密度分析2. 核密度分析三、结果比对一、人口密度 人口密度是指单位土地面积上居住的人口数,通常以每平方千米或每公顷内的常住人口为单位计算。人口密度同资源、经济密切结合,因此,科学准确地分析人口密度的分布情况,对合理制定…...

Python 安装Vue依赖包发生异常:npm ERR! notsup Required: {“node“:“^18.17.0 || >=20.5.0“}

异常&#xff1a; 原因&#xff1a;node和npm要求升级为高版本 解决&#xff1a;重新安装node环境 &#xff08;1&#xff09; 官网下载Node.js &#xff08;2&#xff09;双击安装node.js &#xff08;3&#xff09;运行查看...

TypeScript 项目 Airbnb 语法风格 ESLint 配置

TypeScript 项目 Airbnb 语法风格 ESLint 配置 1. 配置 安装&#xff1a; npm i -D eslint-config-airbnb-typescript typescript-eslint/eslint-plugin^6.0.0 typescript-eslint/parser^6.0.0配置&#xff1a; .eslintrc.js: module.exports {root: true,env: {node: true…...

怎么使用sentinel,以及所有的知识点

Sentinel是一个开源的流量控制和实时监控系统&#xff0c;主要用于保护企业级应用程序免受不良的请求。下面是使用Sentinel需要了解的知识点&#xff1a; 1. 什么是流量控制&#xff1f; 流量控制指的是限制应用程序的请求流量&#xff0c;防止过多的请求超出系统的承受范围。…...

中国一年有457万人确诊癌症!医生提示:这4种食物,再爱吃也要管住嘴

癌症是威胁人类生命健康的重大疾病&#xff0c;癌症的发生因素一直以来都是专家学者重点探索的课题。据世卫组织最新公布的数据显示&#xff0c;食物或与癌症发生之间存在着密切的联系&#xff0c;某些食物的摄入过多可能会增加患癌症的风险&#xff0c;所以我们应该警惕&#…...

小程序项目:springboot+vue基本微信小程序的宠物领养系统

项目介绍 当今科技发展迅速&#xff0c;交通环境也变得越来越复杂。人们的出行方式变得多元化&#xff0c;这给视障人士带来了一定的困扰。而导盲犬可以帮助视障人士外出行走&#xff0c;提高他们的生活质量。在我国&#xff0c;导盲犬的数量远远少于视障人士的数量。由于导盲…...

数据挖掘 K近邻

什么时候用K近邻&#xff1f; 交叉验证的时候。最常见的交叉验证方法是K折交叉验证&#xff0c;其中数据集被均匀分成K个子集&#xff0c;称为折&#xff0c;然后执行K次训练和测试&#xff0c;每次选择不同的折作为测试集&#xff0c;其余的作为训练集。最后&#xff0c;将K次…...

项目去除git版本控制

我 | 在这里 &#x1f575;️ 读书 | 长沙 ⭐软件工程 ⭐ 本科 &#x1f3e0; 工作 | 广州 ⭐ Java 全栈开发&#xff08;软件工程师&#xff09; &#x1f383; 爱好 | 研究技术、旅游、阅读、运动、喜欢流行歌曲 ✈️已经旅游的地点 | 新疆-乌鲁木齐、新疆-吐鲁番、广东-广州…...

ICMPv6报文与邻居状态跟踪

ICMPv6报文 ICMPv6(Internet Control Message Protocol for the IPv6)是IPv6的基础协议之一。 在IPv4中,Internet控制报文协议ICMP(Internet Control Message Protocol)向源节点报告关于向目的地传输IP数据包过程中的错误和信息。它为诊断、信息和管理目的定义了一些消息…...

React中通过children prop或者React.memo来优化子组件渲染【react性能优化】

文章目录 前言未优化之前的代码问题解决方案一&#xff0c;通过children prop解决方案二&#xff0c;通过React.memo后言 前言 hello world欢迎来到前端的新世界 &#x1f61c;当前文章系列专栏&#xff1a;react.js &#x1f431;‍&#x1f453;博主在前端领域还有很多知识和…...

「Verilog学习笔记」含有无关项的序列检测

专栏前言 本专栏的内容主要是记录本人学习Verilog过程中的一些知识点&#xff0c;刷题网站用的是牛客网 timescale 1ns/1ns module sequence_detect(input clk,input rst_n,input a,output reg match);reg [8:0] a_tem ; always (posedge clk or negedge rst_n) begin if (~rs…...

k8s部署的java服务查看连接nacos缓存的配置文件

一、问题描述 k8s部署的java服务&#xff0c;使用nacos中的配置文件&#xff0c;需要在缓存中查看该服务具体是使用到了哪些配置文件 二、解决 参考文档: https://nacos.io/zh-cn/docs/system-configurations.html 文档描述如下: 进入java服务容器进入用户目录下的nacos&a…...

【matlab程序】matlab给风速添加图例大小

【matlab程序】matlab给风速添加图例大小 clear;clc;close all; % load 加载风速数据。 load(matlab.mat) % 加载颜色包信息 gray load(D:\matlab_work\函数名为colormore的颜色索引表制作\R_color_txt\R_color_single\gray89.txt); brown load(D:\matlab_work\函数名为color…...

微服务学习|初识MQ、RabbitMQ快速入门、SpringAMQP

初识MQ 同步通讯和异步通讯 同步通讯是实时性质的&#xff0c;就好像你用手机与朋友打视频电话&#xff0c;但是&#xff0c;别人再想与你视频就不行了&#xff0c;异步通讯不要求实时性&#xff0c;就好像你用手机发短信&#xff0c;好多人都能同时给你发短信&#xff0c;你…...

【开源】基于Vue.js的固始鹅块销售系统

项目编号&#xff1a; S 060 &#xff0c;文末获取源码。 \color{red}{项目编号&#xff1a;S060&#xff0c;文末获取源码。} 项目编号&#xff1a;S060&#xff0c;文末获取源码。 目录 一、摘要1.1 项目介绍1.2 项目录屏 二、功能模块2.1 数据中心模块2.2 鹅块类型模块2.3 固…...

SpringCloud微服务网关Gateway:gateway基本实现、断言工厂、过滤器工厂、浏览器同源策略、跨域问题解决方案

Gateway网关 Spring Cloud Gateway 是 Spring Cloud 的一个全新项目&#xff0c;该项目是基于 Spring 5.0&#xff0c;Spring Boot 2.0和Project Reactor 等响应式编程和事件流技术开发的网关&#xff0c;它旨在为微服务架构提供一种简单有效的统一的 API路由管理方式 为什么…...

ArcGIS中如何建立土地利用规划数据库

一、建库步骤 - 收集土地利用规划资料,包括图件资料、数据资料和文本资料。 - 将收集到的数据进行整理和格式转换,使其符合ArcGIS 的数据格式要求。 - 在ArcGIS 中创建新的土地利用规划数据库,并定义相应的数据结构和字段。 - 将转换后的数据导入到新的土地利用规划数据库中…...

微信小程序 服务端返回富文本,图片无法显示

场景&#xff1a;   微信小程序开发中&#xff0c;需要从服务端拿取数据渲染到页面上&#xff0c;后台返回的富文本里&#xff0c;图片路径有时是没有带域名前缀的&#xff0c;导致图片无法正常显示。 解决方案&#xff1a;   在富文本返回时&#xff0c;用正则匹配&#…...

Java 语言特性(面试系列2)

一、SQL 基础 1. 复杂查询 &#xff08;1&#xff09;连接查询&#xff08;JOIN&#xff09; 内连接&#xff08;INNER JOIN&#xff09;&#xff1a;返回两表匹配的记录。 SELECT e.name, d.dept_name FROM employees e INNER JOIN departments d ON e.dept_id d.dept_id; 左…...

【WiFi帧结构】

文章目录 帧结构MAC头部管理帧 帧结构 Wi-Fi的帧分为三部分组成&#xff1a;MAC头部frame bodyFCS&#xff0c;其中MAC是固定格式的&#xff0c;frame body是可变长度。 MAC头部有frame control&#xff0c;duration&#xff0c;address1&#xff0c;address2&#xff0c;addre…...

汇编常见指令

汇编常见指令 一、数据传送指令 指令功能示例说明MOV数据传送MOV EAX, 10将立即数 10 送入 EAXMOV [EBX], EAX将 EAX 值存入 EBX 指向的内存LEA加载有效地址LEA EAX, [EBX4]将 EBX4 的地址存入 EAX&#xff08;不访问内存&#xff09;XCHG交换数据XCHG EAX, EBX交换 EAX 和 EB…...

大学生职业发展与就业创业指导教学评价

这里是引用 作为软工2203/2204班的学生&#xff0c;我们非常感谢您在《大学生职业发展与就业创业指导》课程中的悉心教导。这门课程对我们即将面临实习和就业的工科学生来说至关重要&#xff0c;而您认真负责的教学态度&#xff0c;让课程的每一部分都充满了实用价值。 尤其让我…...

如何在网页里填写 PDF 表格?

有时候&#xff0c;你可能希望用户能在你的网站上填写 PDF 表单。然而&#xff0c;这件事并不简单&#xff0c;因为 PDF 并不是一种原生的网页格式。虽然浏览器可以显示 PDF 文件&#xff0c;但原生并不支持编辑或填写它们。更糟的是&#xff0c;如果你想收集表单数据&#xff…...

C++使用 new 来创建动态数组

问题&#xff1a; 不能使用变量定义数组大小 原因&#xff1a; 这是因为数组在内存中是连续存储的&#xff0c;编译器需要在编译阶段就确定数组的大小&#xff0c;以便正确地分配内存空间。如果允许使用变量来定义数组的大小&#xff0c;那么编译器就无法在编译时确定数组的大…...

C++.OpenGL (14/64)多光源(Multiple Lights)

多光源(Multiple Lights) 多光源渲染技术概览 #mermaid-svg-3L5e5gGn76TNh7Lq {font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}#mermaid-svg-3L5e5gGn76TNh7Lq .error-icon{fill:#552222;}#mermaid-svg-3L5e5gGn76TNh7Lq .erro…...

苹果AI眼镜:从“工具”到“社交姿态”的范式革命——重新定义AI交互入口的未来机会

在2025年的AI硬件浪潮中,苹果AI眼镜(Apple Glasses)正在引发一场关于“人机交互形态”的深度思考。它并非简单地替代AirPods或Apple Watch,而是开辟了一个全新的、日常可接受的AI入口。其核心价值不在于功能的堆叠,而在于如何通过形态设计打破社交壁垒,成为用户“全天佩戴…...

Docker拉取MySQL后数据库连接失败的解决方案

在使用Docker部署MySQL时&#xff0c;拉取并启动容器后&#xff0c;有时可能会遇到数据库连接失败的问题。这种问题可能由多种原因导致&#xff0c;包括配置错误、网络设置问题、权限问题等。本文将分析可能的原因&#xff0c;并提供解决方案。 一、确认MySQL容器的运行状态 …...

五子棋测试用例

一.项目背景 1.1 项目简介 传统棋类文化的推广 五子棋是一种古老的棋类游戏&#xff0c;有着深厚的文化底蕴。通过将五子棋制作成网页游戏&#xff0c;可以让更多的人了解和接触到这一传统棋类文化。无论是国内还是国外的玩家&#xff0c;都可以通过网页五子棋感受到东方棋类…...