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

【JS】Object.defineProperty与Proxy

一、Object.defineProperty

这里只是简单描述,具体请看另一篇文章:Object.defineProperty。

Object.defineProperty 是 JavaScript 中用于定义或修改对象属性的功能强大的方法。它可以精确地控制属性的行为,如是否可枚举、可配置、可写等。

基本用法

Object.defineProperty(obj, prop, descriptor)

Object.defineProperty 方法接受三个参数:

  1. 『目标对象』:要在其上定义属性的对象。
  2. 『属性名称』:要定义或修改的属性名称。
  3. 『描述符对象』:属性描述符对象,用于描述该属性的行为。
    属性描述符对象可以包含以下键:
    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 构造函数接受两个参数:

  1. target:要包装的目标对象(可以是任何类型的对象,包括数组、函数等)。
  2. 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.definePropertyProxy
拦截范围只能拦截对象的单个属性操作,即只能定义特定属性的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排序的概念 排序&#xff1a;排列或排序是将一组数据按照一定的规则或顺序重新组织的过程&#xff0c;数据既可以被组织成递增顺序&#xff08;升序&#xff09;&#xff0c;或者递减顺序&#xff08;降序&#xff09;。稳定性&#xff1a;假定在待…...

【Unity】RPG2D龙城纷争(十九)流程与UI界面(终章)

更新日期:2024年8月1日。 项目源码:第五章发布(正式开始游戏逻辑的章节) 索引 简介一、游戏流程1.初始化流程2.开始流程3.关卡流程4.关卡结束流程5.启用所有流程二、UI界面逻辑1.开始界面2.存档界面3.关卡界面DataRegion 数据显示逻辑区域RoundRegion 回合逻辑区域RoleMenu…...

C#类和结构体的区别

1、类class是引用类型&#xff0c;多个引用类型变量的值会互相影响。存储在堆&#xff08;heap&#xff09;上 2、结构体struct是值类型&#xff0c;多个值类型变量的值不会互相影响。存储在栈&#xff08;stack&#xff09;上 类结构关键字classstruct类型引用类型值类型存储…...

【RabbitMQ】RabbitMQ持久化

一、简介 RabbitMQ的持久化机制是一种确保数据在RabbitMQ服务重启或异常情况下不会丢失的重要特性。RabbitMQ的持久化主要包括三个方面的内容&#xff1a;交换器的持久化、队列的持久化、消息的持久化。 二、交换器的持久化 1、实现方式 在RabbitMQ中&#xff0c;实现交换器…...

算法刷题笔记 Kruskal算法求最小生成树(详细算法介绍,详细注释C++代码实现)

文章目录 题目描述基本思路实现代码 题目描述 给定一个n个点m条边的无向图&#xff0c;图中可能存在重边和自环&#xff0c;边权可能为负数。求最小生成树的树边权重之和&#xff0c;如果最小生成树不存在则输出impossible。 最小生成树的概念&#xff1a;给定一张边带权的无向…...

5年经验的软件测试人员,碰到这样的面试题居然会心虚......

我们这边最近的面试机会比较多&#xff0c;但是根据他们的反馈&#xff0c;结束后大部分都没音信了&#xff0c;因为现在企业面试问的非常多&#xff0c;范围非常广&#xff0c;而且开放性的问题很多&#xff0c;很多人即便面试前刷了成百上千道面试题&#xff0c;也很难碰到一…...

C#进阶-轻量级ORM框架Dapper的使用教程与原理详解

本文详细介绍了Dapper在C#中的使用方法&#xff0c;包括Dapper的基本概念、与其他持久层框架的比较、基本语法和高级语法的使用&#xff0c;并通过实例讲解了如何在项目中集成和使用Dapper。Dapper以其高效的性能和简洁的API受到开发者的青睐&#xff0c;适用于各种数据库操作需…...

C++初阶-list的底层

目录 1.std::list实现的所有代码 2.list的简单介绍 2.1实现list的类 2.2_list_iterator的实现 2.2.1_list_iterator实现的原因和好处 2.2.2_list_iterator实现 2.3_list_node的实现 2.3.1. 避免递归的模板依赖 2.3.2. 内存布局一致性 2.3.3. 类型安全的替代方案 2.3.…...

<6>-MySQL表的增删查改

目录 一&#xff0c;create&#xff08;创建表&#xff09; 二&#xff0c;retrieve&#xff08;查询表&#xff09; 1&#xff0c;select列 2&#xff0c;where条件 三&#xff0c;update&#xff08;更新表&#xff09; 四&#xff0c;delete&#xff08;删除表&#xf…...

React hook之useRef

React useRef 详解 useRef 是 React 提供的一个 Hook&#xff0c;用于在函数组件中创建可变的引用对象。它在 React 开发中有多种重要用途&#xff0c;下面我将全面详细地介绍它的特性和用法。 基本概念 1. 创建 ref const refContainer useRef(initialValue);initialValu…...

蓝桥杯 2024 15届国赛 A组 儿童节快乐

P10576 [蓝桥杯 2024 国 A] 儿童节快乐 题目描述 五彩斑斓的气球在蓝天下悠然飘荡&#xff0c;轻快的音乐在耳边持续回荡&#xff0c;小朋友们手牵着手一同畅快欢笑。在这样一片安乐祥和的氛围下&#xff0c;六一来了。 今天是六一儿童节&#xff0c;小蓝老师为了让大家在节…...

React Native在HarmonyOS 5.0阅读类应用开发中的实践

一、技术选型背景 随着HarmonyOS 5.0对Web兼容层的增强&#xff0c;React Native作为跨平台框架可通过重新编译ArkTS组件实现85%以上的代码复用率。阅读类应用具有UI复杂度低、数据流清晰的特点。 二、核心实现方案 1. 环境配置 &#xff08;1&#xff09;使用React Native…...

蓝桥杯3498 01串的熵

问题描述 对于一个长度为 23333333的 01 串, 如果其信息熵为 11625907.5798&#xff0c; 且 0 出现次数比 1 少, 那么这个 01 串中 0 出现了多少次? #include<iostream> #include<cmath> using namespace std;int n 23333333;int main() {//枚举 0 出现的次数//因…...

安宝特方案丨船舶智造的“AR+AI+作业标准化管理解决方案”(装配)

船舶制造装配管理现状&#xff1a;装配工作依赖人工经验&#xff0c;装配工人凭借长期实践积累的操作技巧完成零部件组装。企业通常制定了装配作业指导书&#xff0c;但在实际执行中&#xff0c;工人对指导书的理解和遵循程度参差不齐。 船舶装配过程中的挑战与需求 挑战 (1…...

LINUX 69 FTP 客服管理系统 man 5 /etc/vsftpd/vsftpd.conf

FTP 客服管理系统 实现kefu123登录&#xff0c;不允许匿名访问&#xff0c;kefu只能访问/data/kefu目录&#xff0c;不能查看其他目录 创建账号密码 useradd kefu echo 123|passwd -stdin kefu [rootcode caozx26420]# echo 123|passwd --stdin kefu 更改用户 kefu 的密码…...

云原生安全实战:API网关Kong的鉴权与限流详解

&#x1f525;「炎码工坊」技术弹药已装填&#xff01; 点击关注 → 解锁工业级干货【工具实测|项目避坑|源码燃烧指南】 一、基础概念 1. API网关&#xff08;API Gateway&#xff09; API网关是微服务架构中的核心组件&#xff0c;负责统一管理所有API的流量入口。它像一座…...

GO协程(Goroutine)问题总结

在使用Go语言来编写代码时&#xff0c;遇到的一些问题总结一下 [参考文档]&#xff1a;https://www.topgoer.com/%E5%B9%B6%E5%8F%91%E7%BC%96%E7%A8%8B/goroutine.html 1. main()函数默认的Goroutine 场景再现&#xff1a; 今天在看到这个教程的时候&#xff0c;在自己的电…...