【JS】Object.defineProperty与Proxy
一、Object.defineProperty
这里只是简单描述,具体请看另一篇文章:Object.defineProperty。
Object.defineProperty 是 JavaScript 中用于定义或修改对象属性的功能强大的方法。它可以精确地控制属性的行为,如是否可枚举、可配置、可写等。
基本用法
Object.defineProperty(obj, prop, descriptor)
Object.defineProperty 方法接受三个参数:
- 『目标对象』:要在其上定义属性的对象。
- 『属性名称』:要定义或修改的属性名称。
- 『描述符对象』:属性描述符对象,用于描述该属性的行为。
属性描述符对象可以包含以下键:
value:属性的值。默认为 undefined。
writable:属性是否可写。默认为 false。
configurable:属性是否可配置。默认为 false。
enumerable:属性是否可枚举。默认为 false。
get:属性的 getter 函数。如果没有 getter,值为 undefined。
set:属性的 setter 函数。如果没有 setter,值为 undefined。
用例
1. 定义一个只读属性
let obj = {};Object.defineProperty(obj, 'message', {value: 'Hello, world!',writable: false
});console.log(obj.message); // 输出 "Hello, world!"
obj.message = 'Hi!'; // 无效,因为属性是只读的
console.log(obj.message); // 仍然输出 "Hello, world!"
2. 定义一个不可枚举属性
let obj = {};Object.defineProperty(obj, 'message', {value: 'Hello, world!',enumerable: false
});console.log(obj.message); // 输出 "Hello, world!"
console.log(Object.keys(obj)); // 输出 [], 因为属性不可枚举
3. getter与setter
let obj = {};
let value = 'Hello, world!';Object.defineProperty(obj, 'message', {get() {return value;},set(newValue) {value = newValue;},enumerable: true,configurable: true
});console.log(obj.message); // 输出 "Hello, world!"
obj.message = 'Hi!';
console.log(obj.message); // 输出 "Hi!"
4. 定义不可配置属性
let obj = {};Object.defineProperty(obj, 'message', {value: 'Hello, world!',configurable: false
});console.log(obj.message); // 输出 "Hello, world!"Object.defineProperty(obj, 'message', {value: 'Hi!'
}); // 抛出错误,因为属性不可配置
二、Proxy
Proxy 是 ES6 引入的一项功能,用于定义自定义行为来拦截并改变对某个对象的基本操作(例如属性读取、赋值、枚举、函数调用等)。
基本语法
let proxy = new Proxy(target, handler);
Proxy 构造函数接受两个参数:
- target:要包装的目标对象(可以是任何类型的对象,包括数组、函数等)。
- handler:一个对象,其中包含一组捕捉器(
traps)。这些捕捉器定义了在执行各种操作时,代理对象如何处理这些操作。
捕捉器(Traps)包含:
get(target, prop, receiver):拦截对象属性的读取。
set(target, prop, value, receiver):拦截对象属性的设置。
has(target, prop):拦截 in 操作符。
deleteProperty(target, prop):拦截 delete 操作符。
ownKeys(target):拦截 Object.getOwnPropertyNames 和 Object.getOwnPropertySymbols 方法。
apply(target, thisArg, argumentsList):拦截函数调用。
construct(target, args):拦截 new 操作符。
用例
1. 基本使用
let target = {message: "Hello, world!"
};let handler = {get(target, prop) {return prop in target ? target[prop] : `Property ${prop} does not exist.`;},set(target, prop, value) {console.log(`Setting ${prop} to ${value}`);target[prop] = value;return true;}
};let proxy = new Proxy(target, handler);console.log(proxy.message); // 输出 "Hello, world!"
console.log(proxy.nonExistent); // 输出 "Property nonExistent does not exist."
proxy.message = "Hi!"; // 输出 "Setting message to Hi!"
2. 拦截函数调用
let target = function() {return "I am the target";
};let handler = {apply(target, thisArg, argumentsList) {return "I am the proxy";}
};let proxy = new Proxy(target, handler);console.log(proxy()); // 输出 "I am the proxy"
3. 拦截属性删除
let target = {message: "Hello, world!"
};let handler = {deleteProperty(target, prop) {if (prop in target) {delete target[prop];console.log(`Property ${prop} deleted`);return true;} else {console.log(`Property ${prop} does not exist`);return false;}}
};let proxy = new Proxy(target, handler);delete proxy.message; // 输出 "Property message deleted"
delete proxy.nonExistent; // 输出 "Property nonExistent does not exist"
三、二者对比
代理的粒度不同
defineProperty 只能代理属性,Proxy 代理的是对象。
defineProperty 如果想代理对象的所有属性,需要遍历并为每个属性添加 setter 和 getter。
Proxy 只需要配置一个可以获取属性名参数的函数即可。
是否破坏原对象
defineProperty 的代理行为会破坏原对象,它会将原本的 value 变成了 setter 和 getter。
Proxy 则不会破坏原对象,只是在原对象上覆盖了一层。当新增属性时,希望属性被代理,defineProperty 需要显式调用该 API,而 Proxy 则可以直接用 obj.key = val的形式
| Object.defineProperty | Proxy | |
|---|---|---|
| 拦截范围 | 只能拦截对象的单个属性操作,即只能定义特定属性的getter和setter | 可以拦截对对象的所有操作,包括属性访问、赋值、删除、函数调用等,可以使用get、set、deleteProperty等捕捉器来拦截这些操作 |
| 动态属性 | 不可以处理动态属性 | 可以处理对象的动态添加和删除属性 |
| 是否破坏原对象 | 是 | 否 |
| 性能 | 性能逊于Proxy | 对于处理嵌套对象和大量属性的情况,性能好 |
| 兼容性 | 兼容性更好 | 由于ES6中才引入Proxy,所以兼容性略差 |
四、与Vue2、Vue3的关系
vue2响应式数据原理是Object.defineProperty。
Vue3响应式数据原理是Proxy。
相关文章:
【JS】Object.defineProperty与Proxy
一、Object.defineProperty 这里只是简单描述,具体请看另一篇文章:Object.defineProperty。 Object.defineProperty 是 JavaScript 中用于定义或修改对象属性的功能强大的方法。它可以精确地控制属性的行为,如是否可枚举、可配置、可写等。…...
《计算机网络》(第8版)第8章 互联网上的音频/视频服务 复习笔记
第 8 章 互联网上的音频/视频服务 一、概述 1 多媒体信息的特点 多媒体信息(包括声音和图像信息)最主要的两个特点如下: (1)多媒体信息的信息量往往很大; (2)在传输多媒体数据时&a…...
linux进程控制——进程替换——exec函数接口
前言: 本节内容进入linux进程控制板块的最后一个知识点——进程替换。 通过本板块的学习, 我们了解了进程的基本控制方法——进程创建, 进程退出, 进程终止, 进程替换。 进程控制章节和上一节进程概念板块都是在谈进程…...
Apache解析漏洞~CVE-2017-15715漏洞分析
Apache解析漏洞 漏洞原理 # Apache HTTPD 支持一个文件拥有多个后缀,并为不同后缀执行不同的指令。比如如下配置文件: AddType text/html .html AddLanguage zh-CN .cn# 其给 .html 后缀增加了 media-type ,值为 text/html ;给 …...
Xilinx管脚验证流程及常见问题
1 流程 1.1 新建I/O Planning Project I/O Planning Project中可以不需要RTL的top层.v代码,仅图形化界面即可配置管脚约束XDC文件的生成: Create I/O Ports: 导出XDC文件和自动生成的top_interface.v文件: 1.2 新建test Project …...
格雷厄姆的《聪明的投资者》被誉为“投资圣经”
本杰明格雷厄姆的《聪明的投资者》(The Intelligent Investor: A Book of Practical Counsel)是投资领域的一部经典之作,被誉为“投资圣经”。以下是对该书的详细解析: 一、书籍基本信息 书名:《聪明的投资者》&…...
TypeScript声明文件
TypeScript声明文件 在JavaScript的生态系统中,随着项目的复杂度和规模不断增加,开发者对于类型安全和代码质量的追求也日益增长。TypeScript,作为JavaScript的一个超集,通过添加静态类型检查和ES6等新特性支持,极大地…...
.NET_WPF_使用Livecharts数据绑定图表
相关概念 LiveCharts 是一个开源的图表库,适用于多种 .NET 平台,包括 WPF、UWP、WinForms 等。LiveCharts 通过数据绑定与 MVVM 模式兼容,使得视图模型可以直接控制图表的显示,无需直接操作 UI 元素。这使得代码更加模块化&#x…...
一句JS代码,实现随机颜色的生成
今天我们只用 一句JS代码,实现随机颜色的生成,首先看一下效果: 每次刷新浏览器背景颜色都不一样 实现此效果的JS函数 : let randomColor () > ...: 定义一个箭头函数randomColor,用于生成一个随机颜色。 Math.ra…...
校园抢课助手【7】-抢课接口限流
在上一节中,该接口已经接受过风控的处理,过滤掉了机器人脚本请求,剩下都是人为的下单请求。为了防止用户短时间内高频率点击抢课链接,海量请求造成服务器过载,这里使用接口限流算法。 先介绍下几种常用的接口限流策略…...
char类型和int类型
一、char类型 在Java中,char(字符)类型用于表示单个字符,它是基本数据类型之一。以下是关于Java中char类型的一些重要信息: 表示方式: char类型用于存储Unicode字符,占用16位(即2个字…...
C++参悟:stl中的比较最大最小操作
stl中的比较最大最小操作 一、概述二、最小值1. min2. min_element 三、最大值1. max2. max_element 四、混合1. minmax2. minmax_element 一、概述 记录这里C11中常用的最小值和最大值的比较函数,最好的参考资料其实就是 https://zh.cppreference.com 最重要的查…...
JAVA读取netCdf文件并绘制热力图
读取netCdf的依赖 <dependency><groupId>ucar</groupId><artifactId>netcdfAll</artifactId><version>5.5.3</version><scope>system</scope><exclusions><exclusion><groupId>org.slf4j</groupId…...
数据结构——八大排序
一.排序的概念和其应用 1.1排序的概念 排序:排列或排序是将一组数据按照一定的规则或顺序重新组织的过程,数据既可以被组织成递增顺序(升序),或者递减顺序(降序)。稳定性:假定在待…...
【Unity】RPG2D龙城纷争(十九)流程与UI界面(终章)
更新日期:2024年8月1日。 项目源码:第五章发布(正式开始游戏逻辑的章节) 索引 简介一、游戏流程1.初始化流程2.开始流程3.关卡流程4.关卡结束流程5.启用所有流程二、UI界面逻辑1.开始界面2.存档界面3.关卡界面DataRegion 数据显示逻辑区域RoundRegion 回合逻辑区域RoleMenu…...
C#类和结构体的区别
1、类class是引用类型,多个引用类型变量的值会互相影响。存储在堆(heap)上 2、结构体struct是值类型,多个值类型变量的值不会互相影响。存储在栈(stack)上 类结构关键字classstruct类型引用类型值类型存储…...
【RabbitMQ】RabbitMQ持久化
一、简介 RabbitMQ的持久化机制是一种确保数据在RabbitMQ服务重启或异常情况下不会丢失的重要特性。RabbitMQ的持久化主要包括三个方面的内容:交换器的持久化、队列的持久化、消息的持久化。 二、交换器的持久化 1、实现方式 在RabbitMQ中,实现交换器…...
算法刷题笔记 Kruskal算法求最小生成树(详细算法介绍,详细注释C++代码实现)
文章目录 题目描述基本思路实现代码 题目描述 给定一个n个点m条边的无向图,图中可能存在重边和自环,边权可能为负数。求最小生成树的树边权重之和,如果最小生成树不存在则输出impossible。 最小生成树的概念:给定一张边带权的无向…...
5年经验的软件测试人员,碰到这样的面试题居然会心虚......
我们这边最近的面试机会比较多,但是根据他们的反馈,结束后大部分都没音信了,因为现在企业面试问的非常多,范围非常广,而且开放性的问题很多,很多人即便面试前刷了成百上千道面试题,也很难碰到一…...
C#进阶-轻量级ORM框架Dapper的使用教程与原理详解
本文详细介绍了Dapper在C#中的使用方法,包括Dapper的基本概念、与其他持久层框架的比较、基本语法和高级语法的使用,并通过实例讲解了如何在项目中集成和使用Dapper。Dapper以其高效的性能和简洁的API受到开发者的青睐,适用于各种数据库操作需…...
基于MCP与Apify构建AI驱动的投资另类数据研究工具
1. 项目概述:当投资研究遇上AI代理如果你是一名量化研究员、对冲基金分析师,或者只是一个对金融市场充满好奇、希望用数据驱动决策的独立投资者,那么你肯定对“另类数据”这个词不陌生。传统的财报、股价、宏观经济指标,这些“传统…...
gwadd:轻量级Git仓库组管理工具,提升多项目开发效率
1. 项目概述:一个被低估的Git仓库管理利器如果你和我一样,日常工作中需要频繁地在多个Git仓库之间穿梭,处理各种依赖、子模块,或者仅仅是同步一堆相关的项目代码,那么你一定对那种重复、繁琐的切换和操作感到头疼。今天…...
EL电致发光线与3D打印技术打造可穿戴发光骨架服
1. 项目概述:当发光骨架“活”过来每年万圣节,看着满大街的“幽灵”和“僵尸”,我总想搞点不一样的。直到去年,我决定不再满足于商店里千篇一律的服装,而是想自己动手,做一件真正能“发光”的、有科技感的骨…...
MacOS光标增强工具:命令行驱动,实现自动化与个性化配置
1. 项目概述:当光标成为生产力工具如果你是一名长期在macOS上工作的开发者、设计师或者文字工作者,你肯定对系统自带的光标功能又爱又恨。爱的是它简洁流畅,恨的是它在某些高强度、多任务场景下显得力不从心。比如,当你需要在多个…...
Linux内核C11升级:从C89到现代C语言的演进与挑战
1. 项目概述:一次内核语言的“心脏移植”手术最近Linux内核社区放出了一个重磅消息,未来计划将内核的C语言标准从使用了二十多年的C89/C90,升级到C11。这个消息一出,在开发者圈子里激起的讨论,不亚于当年从Python 2迁移…...
【目标检测系统网页版】基于YOLOv8的淡水鱼检测系统
【目标检测系统网页版】基于YOLOv8的淡水鱼检测系统 一、系统介绍 1、系统简介 基于YOLOv8的淡水鱼检测 Web 系统,支持单图检测、批量图片检测、视频检测与实时视频流检测。 2、功能特性 智能识别:YOLOv8 封装,单例加载,自动设…...
出门在外也能用!OpenAI 将 Codex 接入 ChatGPT 移动端
曾经在企业办公室工作过的人,可能都见过这样的场景:同事们把笔记本电脑托在手臂上,从一个会议室走到另一个会议室。倒也不是非要在走廊、电梯或楼道里处理邮件,只是不想合上盖子然后再等电脑重启。看似有些滑稽,但又不…...
RT-Thread SMP启动流程深度解析:从多核同步到调度就绪
1. 项目概述:从单核到多核,RT-Thread的启动逻辑变迁如果你是从RT-Thread 3.x版本一路用过来的老用户,或者刚开始接触RT-Thread 4.x,可能会发现一个显著的变化:启动流程变“复杂”了。以前,一个main函数或者…...
暗黑破坏神II终极角色编辑器:Diablo Edit2完全使用指南
暗黑破坏神II终极角色编辑器:Diablo Edit2完全使用指南 【免费下载链接】diablo_edit Diablo II Character editor. 项目地址: https://gitcode.com/gh_mirrors/di/diablo_edit Diablo Edit2是暗黑破坏神II玩家必备的角色存档编辑器,这款开源工具…...
SAP F110自动付款:从零到精通的配置全景图
1. SAP F110自动付款入门指南 第一次接触SAP F110自动付款功能时,我也被那一堆配置项搞得晕头转向。记得当时为了搞清楚银行确定逻辑,整整花了两天时间反复测试。现在回想起来,如果有个系统性的指导手册,至少能节省一半时间。F110…...
