JavaScript 对象管家 Proxy
JavaScript 在 ES6 中,引入了一个新的对象类型 Proxy
,它可以用来代理另一个对象,并可以在代理过程中拦截、覆盖和定制对象的操作。Proxy
对象封装另一个对象并充当中间人,其提供了一个捕捉器函数,可以在代理对象上拦截所有的操作,包括访问属性、赋值属性、函数调用等等。通过拦截这些操作,可以对代理对象进行定制和控制。
在开始介绍 Proxy
对象前先了解 3 个术语:
target 目标对象
:要代理的对象或函数。handler 处理程序
:对代理的对象或函数执行某些操作的函数。traps 捕捉器
:这些是一些用于处理目标的函数。单击此处阅读有关陷阱的更多信息。
语法
Proxy
对象的基本语法如下:
new Proxy(target, handler);
其中,target
是被代理的目标对象,handler
是一个对象,它包含了一些捕捉器函数,用来拦截代理对象的操作。
下面是一些常见的拦截操作和对应的捕捉器函数:
对象方法
getPrototypeOf()
:Object.getPrototypeOf
方法的捕捉器。setPrototypeOf()
:Object.setPrototypeOf
方法的捕捉器。isExtensible()
:Object.isExtensible
方法的捕捉器。preventExtensions()
:Object.preventExtensions
方法的捕捉器。getOwnPropertyDescriptor()
:Object.getOwnPropertyDescriptor
方法的捕捉器。handler.defineProperty()
:Object.defineProperty
方法的捕捉器。
属性获取器/设置器
get(target, propKey, receiver)
:拦截对象的读取属性操作,返回属性值。set(target, propKey, value, receiver)
:拦截对象的设置属性操作,返回一个布尔值表示是否设置成功。has(target, propKey)
:拦截对象的in
操作符,返回一个布尔值表示对象是否包含该属性。deleteProperty(target, propKey)
:拦截对象的delete
操作符,返回一个布尔值表示是否删除成功。ownKeys()
:Object.getOwnPropertyNames
方法和Object.getOwnPropertySymbols
方法的捕捉器
函数方法
如果目标对象是一个函数,可以使用下面 2 个捕捉器。
apply(target, thisArg, args)
:拦截函数的调用操作,返回调用结果。construct(target, args, newTarget)
:拦截new
操作符,返回一个对象。
Proxy
在目标对象周围创建一个不可检测的屏障,将所有操作重定向到处理程序对象。如果发送一个空的 handler
,代理只是原始对象的一个空包装器。
const author = {name: "Quintion",age: 36,
};const proxyAuthor = new Proxy(author, {});console.log(author.name); // Quintion
console.log(proxyAuthor.name); // Quintion
为了赋予代理意义,需要向处理程序添加一些操作方法。
捕捉器
每当与一个对象交互时,都在调用一个内部方法。代理允许使用捕捉器拦截给定内部方法的执行。
因此,当运行 author.name
时,告诉 JavaScript 引擎调用内部 [[GET]]
方法来检索 name
属性。当运行 proxyAuthor.name
时,get
捕捉器会调用处理程序中定义的 get()
函数来执行,然后再将调用发送到原始对象。
get
get()
方法有两个必需的参数:
target
— 传递给代理的对象。property
— 访问的属性的名称。
要自定义代理,在处理程序对象上定义函数。下面定义了 get
方法来记录访问:
const handler = {get(target, property) {console.log(`捕捉器 GET:${property}`);return target[property];},
};
为了让调用通过,捕捉器 get
返回 target[property]
。使用方式如下:
const author = {name: "Quintion",age: 36,
};const handler = {get(target, property) {console.log(`捕捉器 GET[${property}]`);return target[property];},
};const proxyAuthor = new Proxy(author, handler);console.log(proxyAuthor.name);
执行后,将打印以下内容:
捕捉器 GET[name]
Quintion
set
set
捕捉器用于给目标对象进行赋值操作,返回值是一个布尔值。set
捕捉器需要的参数如下:
target
— 传递给代理的对象。property
— 将被设置的属性名或 Symbol。value
— 新的属性值receiver
— 最初被调用的对象。
下面通过 set
捕捉器验证年龄值的输入:
const handler = {set(target, property, value) {if (property === "age" && typeof value !== "number") {throw new TypeError("年龄必须是一个数字");}target[property] = value;return true;},
};
下面尝试将错误的类型值赋值给 age
,则会抛出错误:
const proxyAuthor = new Proxy(author, handler);proxyAuthor.age = "young";
// 执行后抛出异常:throw new TypeError("年龄必须是一个数字");
set()
方法应该返回一个布尔值true
用来表示赋值成功。 在严格模式下运行,并且返回一个假值或什么都不返回,则会抛出错误。
除了拦截对属性的读取和修改,Proxy
总共可以拦截 13 种操作。
应用场景
通过 Proxy
对象的特征,可以将其使用在下面这些场合:
验证和过滤
代理Proxy
用于拦截和验证对对象属性的访问。如,可以创建一个代理来检查用户输入的数据是否符合预期的格式,并拒绝不正确的数据。就如下面 age
属性赋值判断
缓存
代理Proxy
用于缓存对象的操作结果,以避免重复计算。如,可以创建一个代理来拦截对象的某些方法,并将结果存储在缓存中,以便将来使用。
下面是一个基于 Proxy 的缓存库的示例:
class Cache {constructor() {this.cache = new Map();this.proxy = new Proxy(this, {get(target, property) {if (property === "get") {return (key) => {return target.cache.get(key);};}if (property === "set") {return (key, value) => {target.cache.set(key, value);};}if (property === "has") {return (key) => {return target.cache.has(key);};}if (property === "delete") {return (key) => {return target.cache.delete(key);};}},});}
}
在上面的代码中,定义了一个 Cache
类,该类中包含一个内部的 Map
对象用于存储缓存数据,并且定义了一个 proxy
对象作为该类的代理。
在 proxy
对象的 get
方法中,根据传入的属性名返回相应的方法。如果属性名为 get
,则返回一个可以获取缓存值的方法;如果属性名为 set
,则返回一个可以设置缓存值的方法;如果属性名为 has
,则返回一个可以判断是否存在缓存值的方法;如果属性名为 delete
,则返回一个可以删除缓存值的方法。
下面是一个使用该缓存库的示例:
const cacheHelper = new Cache();cacheHelper.set("foo", "bar");
console.log(cacheHelper.get("foo")); // "bar"
console.log(cacheHelper.has("foo")); // truecacheHelper.delete("foo");
console.log(cacheHelper.get("foo")); // undefined
console.log(cacheHelper.has("foo")); // false
在上面的代码中,创建了一个 Cache
对象,并调用其 set
方法设置缓存值,然后调用其 get
方法获取缓存值,并调用其 has 方法判断缓存值是否存在,最后调用其 delete
方法删除缓存值。
监听属性变化
代理Proxy
用于监视对象属性的变化,并在属性发生变化时触发其他操作。如,创建一个代理来监视对象属性的变化,并在属性发生变化时更新页面上的元素。
防止误操作
代理Proxy
用于防止误操作,如,创建一个代理来拦截对象的某些方法,并在方法调用时检查一些条件,以确保方法只在正确的上下文中调用。
虚拟化
代理Proxy
可以用于创建虚拟化对象。如,创建一个代理对象,用于代替某个对象的真实实现,并且在实际对象执行之前,对其进行修改或拦截。
总结
上面介绍了如何使用代理Proxy
对象来监视对象,通过使用处理程序对象中的捕捉器方法向它们添加自定义行为,提供更高级的对象操作和控制功能,从而增强代码的可读性和可维护性。
相关文章:

JavaScript 对象管家 Proxy
JavaScript 在 ES6 中,引入了一个新的对象类型 Proxy,它可以用来代理另一个对象,并可以在代理过程中拦截、覆盖和定制对象的操作。Proxy 对象封装另一个对象并充当中间人,其提供了一个捕捉器函数,可以在代理对象上拦截…...

Qt + Vs联合开发
Qt + Vs联合开发 文章目录 Qt + Vs联合开发环境说明VS+Qt安装注意事项QtCreator msvc编译器配置Visual Studio 2019 + Qt 5.12.10Visual Studio 2015 + Qt5.12.10VsQt环境配置安装插件 Qt Visual Studio Tools插件配置Qt创建项目Vs创建Qt项目VsQt工程转换Vs工程转Qt工程Qt工程转…...

开源知识库平台Raneto--使用Docker部署Raneto
文章目录 一、Raneto介绍1.1 Raneto简介1.2 知识库介绍 二、阿里云环境2.1 环境规划2.2 部署介绍 三、环境检查3.1 检查Docker服务状态3.2 检查Docker版本3.3 检查docker compose 版本 四、下载Raneto镜像五、部署Raneto知识库平台5.1 创建挂载目录5.2 编辑config.js文件5.3 编…...

鸿蒙原OS开发实例:【ArkTS类库单次I/O任务开发】
Promise和async/await提供异步并发能力,适用于单次I/O任务的场景开发,本文以使用异步进行单次文件写入为例来提供指导。 实现单次I/O任务逻辑。 import fs from ohos.file.fs; import common from ohos.app.ability.common;async function write(data:…...

C语言:二叉树的构建
目录 一、二叉树的存储 1.1 顺序存储 1.2 链式存储 二、二叉树的顺序结构及实现 2.1堆的概念及结构 2.2堆的构建 2.3堆的插入 2.4堆顶的删除 2.5堆的完整代码 三、二叉树的链式结构及实现 3.1链式二叉树的构建 3.2链式二叉树的遍历 3.2.1前序遍历 …...
软件测试工程师面试汇总功能测试篇
Q:一、进行测试用例设计的时候用到的方法有哪些? A:最常使用的测试用例设计方法包括等价类划分法、边界值分析方法、场景法、错误推测法。其中,最容易 发现错误的是边界值法,使用最多的是场景法。以注册为例:首先从需求确定用户名…...
javaAPI1
API application pragramming interface 应用程序编程接口 除java.lang包以外,其他包中的类在使用时需要导入 建包 package com.abc.javabean; 导包格式,import 包名.类名 API使用技巧 1,先看关键字 2,看参数列表 3,看返回值类型 String 封装字符串和处理字符串的类…...

案例研究|DataEase实现物业数据可视化管理与决策支持
河北隆泰物业服务有限责任公司(以下简称为“隆泰物业”)创建于2002年,总部设在河北省高碑店市,具有国家一级物业管理企业资质,通过了质量体系、环境管理体系、职业健康安全管理体系等认证。自2016年至今,隆…...

Android Studio Iguana | 2023.2.1 补丁 1
Android Studio Iguana | 2023.2.1 Canary 3 已修复的问题Android Gradle 插件 问题 295205663 将 AGP 从 8.0.2 更新到 8.1.0 后,任务“:app:mergeReleaseClasses”执行失败 问题 298008231 [Gradle 8.4][升级] 由于使用 kotlin gradle 插件中已废弃的功能&#…...

iOS17 隐私协议适配详解
1. 背景 网上搜了很多文章,总算有点头绪了。其实隐私清单最后做出来就是一个plist文件。找了几个常用三方已经配好的看了看,比着做就好了。 WWDC23 中关于隐私部分的更新(WWDC23 隐私更新官网),其中提到了第三方 SDK 的…...

LeetCode 每日一题 Day 116-122
2580. 统计将重叠区间合并成组的方案数 给你一个二维整数数组 ranges ,其中 ranges[i] [starti, endi] 表示 starti 到 endi 之间(包括二者)的所有整数都包含在第 i 个区间中。 你需要将 ranges 分成 两个 组(可以为空…...

linux离线安装jenkins及使用教程
本教程采用jenkins.war的方式离线安装部署,在线下载的方式会遇到诸多问题,不宜采用 基本环境: 1.jdk环境,Jenkins是java语言开发的,因需要jdk环境。 2.git/svn客户端,因一般代码是放在git/svn服务器上的&a…...

NXP-S32DS软件安装
文章目录 一、安装包获取二、S32DS安装三、芯片插件安装 一、安装包获取 登录NXP官网,进入软件目录https://www.nxp.com/ 下载S32DS软件和RTD驱动库,并安装S32DS软件。 单击“S32DS.3.5_b220726_win32.x86_64.exe”下载该软件 点击“License Keys”&…...

26版SPSS操作教程(初级第十五章)
前言 #由于导师最近布置了学习SPSS这款软件的任务,因此想来平台和大家一起交流下学习经验,这期推送内容接上一次第十四章的学习笔记,希望能得到一些指正和帮助~ 粉丝及官方意见说明 #针对官方爸爸的意见说的推送缺乏操作过程的数据案例文件…...

docker部署实用的运维开发手册
下载镜像 docker pull registry.cn-beijing.aliyuncs.com/wuxingge123/reference:latestdocker-compose部署 vim docker-compose.yml version: 3 services:reference:container_name: referenceimage: registry.cn-beijing.aliyuncs.com/wuxingge123/reference:latestports:…...

Oracle VM(虚拟机)性能监控工具
Oracle VM是一个独立的虚拟化环境,由 Oracle 提供支持和设计,旨在为运行虚拟机提供轻量级、安全的基于服务器的平台。Oracle VM 能够在受支持的虚拟化环境中部署操作系统和应用软件,Oracle VM 将用户和管理员与底层虚拟化技术隔离开来&#x…...

1.8 python 模块 time、random、string、hashlib、os、re、json
ython之模块 一、模块的介绍 (1)python模块,是一个python文件,以一个.py文件,包含了python对象定义和pyhton语句 (2)python对象定义和python语句 (3)模块让你能够有逻辑地…...

iOS苹果签名共享签名是什么以及如何获取?
哈喽,大家好呀,咕噜淼淼又来和大家见面啦,最近有很多朋友都来向我咨询共享签名iOS苹果IPA共享签名是什么,针对这个问题,淼淼来解答一下大家的疑惑并告诉大家iOS苹果ipa共享签名需要如何获取。 现在苹果签名在市场上的…...
python爬虫下载音乐
本文使用创作助手。 你可以使用Python的requests库来实现爬虫下载音乐。以下是一个简单的示例代码: import requestsdef download_music(url, file_path):response requests.get(url)with open(file_path, wb) as file:file.write(response.content)print(f"…...

HarmonyOS实战开发-一次开发,多端部署-视频应用
介绍 随着智能设备类型的不断丰富,用户可以在不同的设备上享受同样的服务,但由于设备形态不尽相同,开发者往往需要针对具体设备修改或重构代码,以实现功能完整性和界面美观性的统一。OpenHarmony为开发者提供了“一次开发&#x…...
KubeSphere 容器平台高可用:环境搭建与可视化操作指南
Linux_k8s篇 欢迎来到Linux的世界,看笔记好好学多敲多打,每个人都是大神! 题目:KubeSphere 容器平台高可用:环境搭建与可视化操作指南 版本号: 1.0,0 作者: 老王要学习 日期: 2025.06.05 适用环境: Ubuntu22 文档说…...
[特殊字符] 智能合约中的数据是如何在区块链中保持一致的?
🧠 智能合约中的数据是如何在区块链中保持一致的? 为什么所有区块链节点都能得出相同结果?合约调用这么复杂,状态真能保持一致吗?本篇带你从底层视角理解“状态一致性”的真相。 一、智能合约的数据存储在哪里…...

C++实现分布式网络通信框架RPC(3)--rpc调用端
目录 一、前言 二、UserServiceRpc_Stub 三、 CallMethod方法的重写 头文件 实现 四、rpc调用端的调用 实现 五、 google::protobuf::RpcController *controller 头文件 实现 六、总结 一、前言 在前边的文章中,我们已经大致实现了rpc服务端的各项功能代…...

visual studio 2022更改主题为深色
visual studio 2022更改主题为深色 点击visual studio 上方的 工具-> 选项 在选项窗口中,选择 环境 -> 常规 ,将其中的颜色主题改成深色 点击确定,更改完成...

剑指offer20_链表中环的入口节点
链表中环的入口节点 给定一个链表,若其中包含环,则输出环的入口节点。 若其中不包含环,则输出null。 数据范围 节点 val 值取值范围 [ 1 , 1000 ] [1,1000] [1,1000]。 节点 val 值各不相同。 链表长度 [ 0 , 500 ] [0,500] [0,500]。 …...

从零开始打造 OpenSTLinux 6.6 Yocto 系统(基于STM32CubeMX)(九)
设备树移植 和uboot设备树修改的内容同步到kernel将设备树stm32mp157d-stm32mp157daa1-mx.dts复制到内核源码目录下 源码修改及编译 修改arch/arm/boot/dts/st/Makefile,新增设备树编译 stm32mp157f-ev1-m4-examples.dtb \stm32mp157d-stm32mp157daa1-mx.dtb修改…...

ServerTrust 并非唯一
NSURLAuthenticationMethodServerTrust 只是 authenticationMethod 的冰山一角 要理解 NSURLAuthenticationMethodServerTrust, 首先要明白它只是 authenticationMethod 的选项之一, 并非唯一 1 先厘清概念 点说明authenticationMethodURLAuthenticationChallenge.protectionS…...

Map相关知识
数据结构 二叉树 二叉树,顾名思义,每个节点最多有两个“叉”,也就是两个子节点,分别是左子 节点和右子节点。不过,二叉树并不要求每个节点都有两个子节点,有的节点只 有左子节点,有的节点只有…...

【数据分析】R版IntelliGenes用于生物标志物发现的可解释机器学习
禁止商业或二改转载,仅供自学使用,侵权必究,如需截取部分内容请后台联系作者! 文章目录 介绍流程步骤1. 输入数据2. 特征选择3. 模型训练4. I-Genes 评分计算5. 输出结果 IntelliGenesR 安装包1. 特征选择2. 模型训练和评估3. I-Genes 评分计…...
Python实现简单音频数据压缩与解压算法
Python实现简单音频数据压缩与解压算法 引言 在音频数据处理中,压缩算法是降低存储成本和传输效率的关键技术。Python作为一门灵活且功能强大的编程语言,提供了丰富的库和工具来实现音频数据的压缩与解压。本文将通过一个简单的音频数据压缩与解压算法…...