object.defineProperty和proxy

1、object.defineProperty()

作用

在一个对象上定义一个新属性,或者修改一个对象的现有属性,并返回这个对象

基本使用

语法:Object.defineProperty(obj, prop, descriptor)

参数:

  1. 要添加属性的对象

  2. 要定义或修改的属性的名称或 [Symbol]

  3. 要定义或修改的属性描述符

监听对象单个属性

let person = {}
let personName = 'lihua'
//在person对象上添加属性name,值为personName
Object.defineProperty(person, 'name', {//但是默认是不可枚举的(for in打印打印不出来),可:enumerable: true//默认不可以修改,可:wirtable:true//默认不可以删除,可:configurable:trueget: function () {return personName},set: function (val) {return name=val}
})
//当读取person对象的name属性时,触发get方法
console.log(person.name)
//当修改person对象的name属性时,触发set方法
personName = 'liming'
//检查后发现,修改成功了
console.log(person.name)

通过这种方法,我们成功监听了person上的name属性的变化。

监听对象上的多个属性

let person = {name: '',age: 0
}
// 实现一个响应式函数
function defineProperty(obj, key, val) {Object.defineProperty(obj, key, {get() {console.log(`访问了${key}属性`)return val},set(newVal) {console.log(`${key}属性被修改为${newVal}了`)val = newVal}})
}
// 实现一个遍历函数Observer
function Observer(obj) {Object.keys(obj).forEach((key) => {defineProperty(obj, key, obj[key])})
}
Observer(person)
console.log(person.age)
person.age = 18
console.log(person.age)

深度监听一个对象

Obsever就是我们想要实现的监听函数,我们预期的目标是:只要把对象传入其中,就可以实现对这个对象的属性监视,即使该对象的属性也是一个对象。我们在defineProperty()函数中,添加一个递归的情况:

function defineProperty(obj, key, val) {//如果某对象的属性也是一个对象,递归进入该对象,进行监听observer(key)Object.defineProperty(obj, key, {get() {console.log(`访问了${key}属性`)return val},set(newVal) {console.log(`${key}属性被修改为${newVal}了`)val = newVal}})
}

当然啦,我们也要在observer里面加一个递归停止的条件:

function Observer(obj) {//如果传入的不是一个对象,returnif (typeof obj !== "object" || obj === null) {return}// for (key in obj) {Object.keys(obj).forEach((key) => {defineProperty(obj, key, obj[key])})// }}

还有一个小问题,如果对某属性进行修改时,如果原本的属性值是一个字符串,但是我们重新赋值了一个对象,我们要如何监听新添加的对象的所有属性呢?其实也很简单,只需要修改set函数:

set(newVal) {// 如果newVal是一个对象,递归进入该对象进行监听observer(newVal)console.log(`${key}属性被修改为${newVal}了`)val = newVal}

监听数组

let arr = [1, 2, 3]
let obj = {}
//把arr作为obj的属性监听
Object.defineProperty(obj, 'arr', {get() {console.log('get arr')return arr},set(newVal) {console.log('set', newVal)arr = newVal}
})
console.log(obj.arr)//输出get arr [1,2,3]  正常
obj.arr = [1, 2, 3, 4] //输出set [1,2,3,4] 正常
obj.arr.push(3) //输出get arr 不正常,监听不到push

通过push方法给数组增加的元素,set方法是监听不到的

事实上,通过索引访问或者修改数组中已经存在的元素,是可以出发get和set的,但是对于通过push、unshift增加的元素,会增加一个索引,这种情况需要手动初始化,新增加的元素才能被监听到。另外, 通过 pop 或 shift 删除元素,会删除并更新索引,也会触发 setter 和 getter 方法。

2、proxy

取代了 Vue2 中的 Object.defineProperty() 机制,用于实现数据响应式

什么是代理?

代理(Proxy)是 ES6 中新增的一个特性,它可以用来自定义对象中的操作。代理是一个对象,它可以拦截并重定义基本操作,如属性查找、赋值、枚举、函数调用等。代理对象可以用来创建一个对象的代理,并且可以拦截对该对象的所有操作。

代理在 Vue3 中的应用

在 Vue3 中,代理机制用于实现数据的响应式。当我们创建一个 Vue 实例时,Vue3 会使用代理机制拦截对数据对象的访问和修改,从而实现数据的响应式。具体来说,Vue3 会创建一个代理对象,将数据对象包裹在其中,并拦截对数据对象的所有操作。当我们访问或修改数据对象中的属性时,实际上是在访问或修改代理对象中的属性,代理对象会拦截这些操作,并执行相应的处理,从而实现数据的响应式。

代理机制的原理

代理机制的原理是通过拦截对象中的操作,并执行自定义的处理来实现的。在 Vue3 中,代理机制用于拦截对数据对象的访问和修改。具体来说,Vue3 会创建一个代理对象,将数据对象包裹在其中,并拦截对数据对象的所有操作。当我们访问或修改数据对象中的属性时,实际上是在访问或修改代理对象中的属性,代理对象会拦截这些操作,并执行相应的处理,从而实现数据的响应式。

代理机制的拦截操作主要包括以下几种:

get:拦截对象属性的读取操作。
set:拦截对象属性的赋值操作。
deleteProperty:拦截对象属性的删除操作。
has:拦截 in 操作符的判断操作。
ownKeys:拦截 Object.keys()、Object.getOwnPropertyNames() 等操作。
apply:拦截函数的调用操作。
construct:拦截 new 操作符的调用操作。


在 Vue3 中,代理机制主要使用 get 和 set 两种拦截操作,用于拦截对数据对象的访问和修改。具体来说,当我们访问一个数据对象中的属性时,代理对象会拦截这个操作,并执行 get 拦截操作,从而获取该属性的值。当我们修改一个数据对象中的属性时,代理对象会拦截这个操作,并执行 set 拦截操作,从而修改该属性的值。在 get 和 set 拦截操作中,代理对象会执行相应的处理,从而实现数据的响应式。

使用Proxy+Reflect实现代理

<!DOCTYPE html>
<html lang="en"><head><meta charset="UTF-8" /><meta name="viewport" content="width=device-width, initial-scale=1.0" /><title>测试Reflect和Proxy</title></head><body><script>// 创建一个处理程序对象const handler = {// 拦截目标对象的属性读取操作get(target, prop, receiver) {console.log(`访问了${prop}属性`);// 使用Reflect.get执行目标对象的属性读取操作return Reflect.get(target, prop, receiver);},// 拦截目标对象的属性设置操作set(target, prop, value, receiver) {console.log(`设置了${prop}属性`);// 使用Reflect.set执行目标对象的属性设置操作return Reflect.set(target, prop, value, receiver);},};// 创建一个目标对象const target = {name: "Alice",age: 20,};// 创建一个代理对象const proxy = new Proxy(target, handler);// 使用代理对象执行各种操作console.log(proxy.name); // 访问了name属性,输出Aliceproxy.age = 21; // 设置了age属性console.log(proxy.age); // 访问了age属性,输出21</script></body>
</html>

3、proxy优势

相比于 Vue2 中的 Object.defineProperty() 机制,代理机制有以下优势:

(1)代理机制可以拦截所有类型的操作,包括属性查找、赋值、枚举、函数调用等,而 Object.defineProperty() 机制只能拦截属性赋值和查找操作。
(2)代理机制可以直接监测对象的属性,而 Object.defineProperty() 机制需要遍历对象的所有属性,并为每个属性添加 getter 和 setter,这在对象属性较多时会影响性能。
(3)代理机制可以监测到对象新增和删除的属性,而 Object.defineProperty() 机制无法监测到这些操作。

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

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

相关文章

泛微ecology开发修炼之旅

我将多年泛微ecology开发经验&#xff0c;进行了总结&#xff0c;然后分享给大家。 泛微开发修炼之旅 泛微开发修炼之旅--01搭建开发环境 泛微开发修炼之旅--02开发接口demo 泛微开发修炼之旅--03常用数据表结构讲解 泛微开发修炼之旅--04常用数据库操作工具类封装 。。。。 我…

iOS ------ 多线程 GCD

一&#xff0c;GCD简介 GCD是Apple开发的一个多线程的较新的解决方案。它主要用于优化应用程序以支持多核处理器以及其他对称处理系统。它是一个在线程池模式的基础上执行的并发任务。 为什么要使用GCD&#xff1f; GCD&#xff01;可用于多核的并行运算GCD会自动利用更多的…

中高级前端开发岗

定位&#xff1a; 日常迭代任务的核心研发&#xff0c;具备高质、高效完成迭代任务的能力。 素质要求&#xff1a; 业务专家或擅长某一方向技术&#xff1b;有较丰富的开发经验&#xff1b;需要具备良好的沟通和协作能力&#xff0c;能够与其他部门和团队进行有效的沟通和协…

Linux配置java,maven,marshalsec环境

文章目录 一. Linux配置java环境1.下载jdk文件2.解压tar.gz文件3.设置java环境变量4.验证是否成功 二. Linux配置maven环境1.下载压缩包2.解压tar.gz3. 配置环境变量 三. Linux配置marshalsec环境 一. Linux配置java环境 1.下载jdk文件 mkdir /opt/javawget https://repo.hua…

STM32使用ST-LINK下载程序中需要注意的几点

使用keil5的ST-link下载界面 前提是ST-LINK已经连接好&#xff0c;&#xff08;下图中是没有连接ST-link设备&#xff09;&#xff0c;只是为了展示如何查看STlink设备是否连接的方式 下载前一定设置下载完成后自启动 这个虽然不是必须&#xff0c;但对立即看到新程序的现象…

CVE-2020-0688 远程代码执行漏洞

CVE-2020-0688 远程代码执行漏洞 漏洞产生的主要原因就是在Exchange ECP组件中发现&#xff0c;邮件服务在安装的过程中不会随机生成秘钥&#xff0c;也就是说所有默认安装的Exchange服务器中的validationKey和decryptionKey的值都是相同的&#xff0c;攻击者可以利用静态秘钥…

【深度学习基础】使用Pytorch搭建DNN深度神经网络与手写数字识别

目录 写在开头 一、DNN的搭建 问题描述与数据集 神经网络搭建 模型训练 模型评估 模型复用 二、手写数字识别 任务描述 数据集 神经网络搭建 模型训练 模型评估 写在最后 写在开头 本文将介绍如何使用PyTorch框架搭建深度神经网络模型。实现模型的搭建、模…

开发数据库的思路

一、设计目的 关系型网络数据库。 二、设计要求&#xff1a; (一)安装快速 安装程序特别简单。 (二)配置简单 最小化配置。 (三)使用简单&#xff0c;高效 程序占用空间小&#xff0c;支持基本的SQL语法。 (四)稳定可靠 尽量不依赖其他不稳定库。 (五)其他要求 属于关系型数…

USART串口外设

USART介绍 USART&#xff1a;另外我们经常还会遇到串口&#xff0c;叫UART&#xff0c;少了个S&#xff0c;就是通用异步收发器&#xff0c;一般我们串口很少使用这个同步功能&#xff0c;所以USART和UART使用起来&#xff0c;也没有什么区别。 其实这个STM32的USART同步模式&a…

大模型日报2024-05-30

大模型日报 2024-05-30 大模型资讯 大型语言模型未来将超越人类金融分析师 摘要: 新研究表明&#xff0c;大型语言模型在金融预测方面表现优于人类专家&#xff0c;为交易策略提供了宝贵的洞见。 DLM技术提高语音识别准确率 摘要: 本文介绍了通过去噪语言模型&#xff08;DLM&a…

创新产品认定进行第三方软件鉴定测试的原因

鉴定测试报告 随着科技的飞速发展&#xff0c;软件产品在各个领域的应用越来越广泛&#xff0c;对于软件产品的质量和安全性要求也越来越高。为了确保软件产品的质量和安全性&#xff0c;创新产品认定进行第三方软件鉴定测试成为了一种必要手段。 一、保障产品质量 第三方软…

在Linux/Ubuntu/Debian上安装TensorFlow 2.14.0

在Ubuntu上安装TensorFlow 2.14.0&#xff0c;可以遵循以下步骤。请注意&#xff0c;由于TensorFlow的版本更新可能很快&#xff0c;这里提供的具体步骤可能需要根据你的系统环境和实际情况进行微调。 准备工作 检查系统要求&#xff1a;确保你的Ubuntu系统满足TensorFlow的运…

洛谷 P3870 [TJOI2009] 开关 题解 线段树

[TJOI2009] 开关 题目描述 现有 n n n 盏灯排成一排&#xff0c;从左到右依次编号为&#xff1a; 1 1 1&#xff0c; 2 2 2&#xff0c;……&#xff0c; n n n。然后依次执行 m m m 项操作。 操作分为两种&#xff1a; 指定一个区间 [ a , b ] [a,b] [a,b]&#xff0c;…

从了解到掌握 Spark 计算框架(二)RDD

文章目录 RDD 概述RDD 组成RDD 的作用RDD 算子分类RDD 的创建1.从外部数据源读取2.从已有的集合或数组创建3.从已有的 RDD 进行转换 RDD 常用算子大全转换算子行动算子 RDD 算子综合练习RDD 依赖关系窄依赖宽依赖宽窄依赖算子区分 RDD 血统信息血统信息的作用血统信息的组成代码…

LM2733升压芯片

具有 40V 内部 FET 开关且采用 SOT-23 封装的 LM2733 0.6MHz 和 1.6MHz 升压转换器 外观 参考价格 1 特性 电路原理图 基于LM2733升压电路设计-CSDN博客https://blog.csdn.net/qq_31251431/article/details/107479885 特此记录 anlog 2024年5月31日 高压方案 此方案经过更多…

MySQL -- SQL笔试题相关

1.银行代缴花费bank_bill 字段名描述serno流水号date交易日期accno账号name姓名amount金额brno缴费网点 serno: 一个 BIGINT UNSIGNED 类型的列&#xff0c;作为主键&#xff0c;且不为空。该列是自动增量的&#xff0c;每次插入新行时&#xff0c;都会自动递增生成一个唯一的…

游戏安全 | 一款「安全」的SLG游戏应该是什么样的?

谈到SLG游戏&#xff0c;也许会想到《万国觉醒》&#xff0c;海外上线5个月后&#xff0c;以5400万美元的月流水创造了新的SLG手游海外收入纪录。 谈到SLG游戏&#xff0c;也许会想到《王国纪元》&#xff0c;通过两军对战的方式&#xff0c;以大面积消灭敌人的攻势&#xff0c…

数据库开发-MySQL01

目录 前言 1. MySQL概述 1.1 安装 1.1.1 版本 1.1.2 安装 1.1.3 连接 1.1.4 企业使用方式(了解) 1.2 数据模型 1.3 SQL简介 1.3.1 SQL通用语法 1.3.2 分类 2. 数据库设计-DDL 2.1 项目开发流程 2.2 数据库操作 2.2.1 查询数据库 2.2.2 创建数据库 2.2.3 使用数…

echarts学习:将echats实例代理为响应式对象可能带来的风险

1.起源 最近我在学习如何封装echarts组件&#xff0c;我所参考的其中一篇博客中提到了一个“图表无法显示的问题”。 根据其中的介绍&#xff0c;造成此种问题的原因是因为&#xff0c;使用ref接受了echarts实例&#xff0c;使得echarts实例被代理为了响应式对象&#xff0c;进…

ChatGPT-4o在临床医学日常工作、论文高效撰写与项目申报、数据分析与可视化、机器学习建模中的应用

ChatGPT-4o在临床医学日常工作、论文高效撰写与项目申报、数据分析与可视化、机器学习建模中的应用 2022年11月30日&#xff0c;可能将成为一个改变人类历史的日子——美国人工智能开发机构OpenAI推出了聊天机器人ChatGPT-3.5&#xff0c;将人工智能的发展推向了一个新的高度。…