为什么vue3要选用proxy,好处是什么?

news2025/8/13 12:16:47

提问

  1. Object.defineProperty()和proxy的区别?
  2. 为什么vue3要选用proxy,好处是什么?

proxy

Proxy 对象用于创建一个对象的代理,从而实现基本操作的拦截和自定义(如属性查找、赋值、枚举、函数调用等)。

Proxy的用法,这个大家都知道

const p = new Proxy(target, handler)

剖析一下内部实现 ECMAScript 2017 (ECMA-262)
在这里插入图片描述

可以看到接收两个参数(target,handler)

  1. 如果target是undefined,报错
  2. 运行ProxyCreate(target, handler)

下面是ProxyCreate的实现

在这里插入图片描述

排除一下错误处理,核心代码从5开始
先创建一个新的空对象p,

设置p对象的内部方法(除了[call]]和[[Construct]])设置为[9.5指定的定义,

然后设置p的call和Construct方法,

再设置内部属性[[ProxyTarget]]和[[ProxyHandler]]

返回对象p

我们可以用它们拦截什么?

对于对象的大多数操作,JavaScript 规范中有一个所谓的“内部方法”,它描述了最底层的工作方式。例如 [[Get]],用于读取属性的内部方法,[[Set]],用于写入属性的内部方法,等等。这些方法仅在规范中使用,我们不能直接通过方法名调用它们。

Proxy 捕捉器会拦截这些方法的调用。它们在 proxy 规范 和下表中被列出。

对于每个内部方法,此表中都有一个捕捉器:可用于添加到 new Proxyhandler 参数中以拦截操作的方法名称:

对于对象的大多数操作,JavaScript 规范中有一个所谓的“内部方法”,它描述了最底层的工作方式。例如 [[Get]],用于读取属性的内部方法,[[Set]],用于写入属性的内部方法,等等。这些方法仅在规范中使用,我们不能直接通过方法名调用它们。

Proxy 捕捉器会拦截这些方法的调用。它们在 proxy 规范 和下表中被列出。

对于每个内部方法,此表中都有一个捕捉器:可用于添加到 new Proxyhandler 参数中以拦截操作的方法名称:

内部方法Handler 方法何时触发
[[Get]]get读取属性
[[Set]]set写入属性
[[HasProperty]]hasin 操作符
[[Delete]]deletePropertydelete 操作符
[[Call]]apply函数调用
[[Construct]]constructnew 操作符
[GetPrototypeOf]]getPrototypeOf[Object.getPrototypeOf
[SetPrototypeOf]]setPrototypeOf[Object.setPrototypeOf
[IsExtensible]]isExtensible[Object.isExtensible
[PreventExtensions]]preventExtensions[Object.preventExtensions
[DefineOwnProperty]]defineProperty[Object.defineProperty, Object.defineProperties
[GetOwnProperty]]getOwnPropertyDescriptor[Object.getOwnPropertyDescriptor, for..in, Object.keys/values/entries
[OwnPropertyKeys]]ownKeys[Object.getOwnPropertyNames, Object.getOwnPropertySymbols, for..in, Object.keys/values/entries

Reflect

Reflect 是一个内建对象,可简化 Proxy 的创建。

前面所讲过的内部方法,例如 [[Get]][[Set]] 等,都只是规范性的,不能直接调用。

Reflect 对象使调用这些内部方法成为了可能。它的方法是内部方法的最小包装。

尤其是,Reflect 允许我们将操作符(newdelete,……)作为函数(Reflect.constructReflect.deleteProperty,……)执行调用。这是一个有趣的功能,但是这里还有一点很重要。

对于每个可被 Proxy 捕获的内部方法,在 Reflect 中都有一个对应的方法,其名称和参数与 Proxy 捕捉器相同。

参考视频讲解:进入学习

所以,我们可以使用 Reflect 来将操作转发给原始对象。

我们可以把捕捉器重写得更短:

get(target, prop, receiver) {
  return Reflect.get( ... arguments);
}

Reflect 调用的命名与捕捉器的命名完全相同,并且接受相同的参数。它们是以这种方式专门设计的。

因此,return Reflect... 提供了一个安全的方式,可以轻松地转发操作,并确保我们不会忘记与此相关的任何内容。

proxy 的局限性

1. 无法代理内部插槽

许多内建对象,例如 MapSetDatePromise 等,都使用了所谓的“内部插槽”。

例如:

let map = new Map();

let proxy = new Proxy(map, {});

proxy.set('test', 1); // Error

解决方法 在get的时候将get要返回的值先绑定目标对象后返回

let map = new Map();

let proxy = new Proxy(map, {
  get(target, prop, receiver) {
    let value = Reflect.get(...arguments);
return typeof value == 'function' ? value.bind(target) : value;
  }
});

proxy.set('test', 1);
alert(proxy.get('test')); // 1(工作了!)

2. 私有字段也和上面一样

3. peoxy != target

这个很好理解 ,代理对象和目标对象是不=== 的

总结

Proxy 是对象的包装器,将代理上的操作转发到对象,并可以选择捕获其中一些操作。

它可以包装任何类型的对象,包括类和函数。

语法为:

let proxy = new Proxy(target, {
  /* trap */
});

……然后,我们应该在所有地方使用 proxy 而不是 target。代理没有自己的属性或方法。如果提供了捕捉器(trap),它将捕获操作,否则会将其转发给 target 对象。

我们可以捕获

  • get,set,deleteProperty 等操作
  • 函数调用(apply捕捉器)
  • new操作(construct 捕捉器)

Reflect 旨在补充 Proxy。对于任意 Proxy 捕捉器,都有一个带有相同参数的 Reflect 调用。我们应该使用它们将调用转发给目标对象。

Proxy的局限

  1. 无法代理内部对象的内部插槽
  2. 无法代理私有字段
  3. 代理对象和目标对象不相等

Object.defineProperty

Object.defineProperty() 方法会直接在一个对象上定义一个新属性,或者修改一个对象的现有属性,并返回此对象。

语法

Object.defineProperties(obj, props)

描述

对象里目前存在的属性描述符有两种主要形式:数据(属性)描述符存取描述符(访问器属性)数据描述符是一个具有值的属性,该值可以是可写的,也可以是不可写的。存取描述符是由 getter 函数和 setter 函数所描述的属性。一个描述符只能是这两者其中之一;不能同时是两者

属性描述符

  • value — 值
  • writable — 如果为 true,则值可以被修改,否则它是只可读的。
  • enumerable — 如果为 true,则会被在循环中列出,否则不会被列出。
  • configurable — 如果为 true,则此属性可以被删除,这些特性也可以被修改,否则不可以。

访问器属性

  • get —— 一个没有参数的函数,在读取属性时工作,
  • set —— 带有一个参数的函数,当属性被设置时调用,
  • enumerable —— 与数据属性的相同,
  • configurable —— 与数据属性的相同。

回答第一个问题

Object.defineProperty()和proxy的区别?

Object.definePropertyProxy
新增/修改一个对象的属性,定义其描述,返回该对象代理目标对象,对其操作拦截,返回代理对象
有数据描述符和访问器描述符两种对其13种操作进行拦截
只能代理常规对象可以代理任何对象(函数,数组,类)
-不能代理内部对象的内部插槽

回答第二个问题

为什么vue3要选用proxy,好处是什么?

  • 能够代理任何对象包括数组和函数,对象
  • 比Object.defineProperty()更多的基本语义得操作(get,set,delete…)
  • 不用循环遍历对象然后再使用Object.defineProperty(),Proxy可以代理对象内所有的属性。
  • Object.defineProperty()只能劫持对象的属性(给对象添加属性vue无法检测到)

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

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

相关文章

微软推出Azure量子资源估算器,加速量子算法研发

​ (图片来源:网络) 近期,微软推出了Azure量子资源估算器,以帮助研发人员检查他们的算法是否可以在未来规模化的量子计算机上运行,并在不同硬件之间进行比较,同时估算在这些系统上执行量子应用…

JVM——垃圾回收机制和内存分配策略

文章目录垃圾回收的垃圾是什么如何判断一个对象是不是垃圾引用计数法可达性分析算法Java的引用垃圾回收基础算法标记清除标记整理标记复制分代垃圾回收GC分析实例HotSpot算法实现细节根节点枚举记忆集与卡表为什么需要记忆集卡表写屏障写屏障(Write Barrier&#xf…

如何实现 MySQL 增删改查操作

文章目录1.新增1.1 不指定列插入1.2 指定列插入1.3 一次性插入多行2.查询2.1 全列查询(查询表中的所有列)2.2 指定列查询2.3 在查寻过程中进行简单计算(列和列之间)2.4 给查询结果的列指定一个别名2.5 查询的时候针对列来去重&…

【AI绘画 | draft意间】国产draft推荐及AI绘画背后的原理解读

个人名片: 🐼作者简介:一名大二在校生,喜欢编程🎋 🐻‍❄️个人主页🥇:小新爱学习. 🐼个人WeChat:hmmwx53 🕊️系列专栏:&#x1f5bc…

计算机网络—网络层

网络协议 IP 概述 因为网络层是整个互联网的核心,因此应当让网络尽可能简单。网络层提供简单灵活的、无连接的、尽最大努力交互的数据报服务。 使用 IP 协议,可以把异构的物理网络连接起来,使网络层像统一的网络 与 IP 协议配套使用有三种…

Molecular Psychiatry:神经成像预测模型在心理健康领域的未来趋势

使用神经成像数据的预测建模有潜力提高我们对精神障碍的神经生物学基础和推定的信息干预的理解。因此,有大量的文献回顾了已发表的研究,机器学习的数学基础,以及使用这些方法的最佳实践。随着我们在心理健康和机器学习方面的知识不断发展&…

【分布式应用】GFS分布式文件系统

文件系统:用于存储和管理文件的相关系统。 FS(文件系统)的作用:从系统角度来看,文件系统是对文件存储设备的空间进行组织和分配,负责文件存储并对存入的文件进行保护和检索的系统。 具体地说,它负责为用户建…

Windows重启时的电脑蓝屏怎么办?

在使用Windows电脑时,最害怕的是遇到系统突然崩溃的情况,特别是出现蓝屏。蓝屏可能会导致数据丢失、无法启动Windows等糟糕的情况。那电脑重启时蓝屏怎么解决? 解决方法一、使用系统还原撤消最近的更改 Windows中的系统还原功能是一个便利的…

html5+css3

目录 一、html简介: 1、什么是网页? 2、什么是html? 3、网页的形成 二、常用的浏览器 三、web标准(重点) 1、为什么要使用web标准? 2、遵循web标准的优点: 四、html语法规范 1、基本语…

Hadoop架构、组件、及其术语汇总和理解

推荐大象教程,介绍Hadoop、HDFS、MapReduce架构和工作原理相对来说非常的清晰。其内容是与《Hadoop the Definitive Guide》基本一致的。讲解的很细致、细节,又带了一些个人的理解和举例子,比较易懂,是比Hadoop官网更值得一看的入…

Assignment写作怎么避免不及格的情况出现?

俗语说得好,犯错误是在所难免的。中西方教育方式大不相同,对Assignment的写作要求也有所不同。刚到国外时,留学生对国外的教育制度和学习过程缺乏了解。难怪在日常学习中,尤其是在英文Assignment写作过程中,留学生都会…

限时开源,来自大佬汇总的Kafka限量笔记,绝对不会后悔!

前言 今天我们来聊聊 Kafka ,主要是带你重新认识一下 Kafka,聊一下 Kafka 中比较重要的概念和问题。 我们现在经常提到 Kafka 的时候就已经默认它是一个非常优秀的消息队列了,我们也会经常拿它给 RocketMQ、RabbitMQ 对比。我觉得 Kafka 相…

GaussDB CN服务异常实例分析

摘要:先通过OPS确认节点状态是否已经恢复,或登录后台执行cm_ctl query -Cv确认集群是否已经Normal。本文分享自华为云社区《【实例状态】GaussDB CN服务异常》,作者:酷哥。 确认节点状态 先通过OPS确认节点状态是否已经恢复&…

sqoop部署

一、实验介绍 1.1实验内容 本次实验包括sqoop安装部署及利用Sqoop在mysql数据库与hive之间进行数据迁移。 1.2实验知识点 Sqoop安装 mysql到Hive数据迁移 1.3实验环境 Sqoop-1.4.7 网易云平台 1.4实验资源 资源名称存储目录Sqoop安装包/opt/software/package/1.5实验步…

原生 canvas 如何实现大屏?

前言 可视化大屏该如何做?有可能一天完成吗?废话不多说,直接看效果,线上 Demo 地址 lxfu1.github.io/large-scree…。 看完这篇文章(这个项目),你将收获: 全局状态真的很简单&…

多篇《Nature》和《Science》关于马约拉纳费米子的研究论文近日被撤稿

马约拉纳费米子(英语:Majorana fermion)是一种假设粒子,它的反粒子就是它本身,1937年,埃托雷马约拉纳发表论文假想这种粒子存在,因此而命名。与之相异,狄拉克费米子,指的…

当大火的文图生成模型遇见知识图谱,AI画像趋近于真实世界

导读 用户生成内容(User Generated Content,UGC)是互联网上多模态内容的重要组成部分,UGC数据级的不断增长促进了各大多模态内容平台的繁荣。在海量多模态数据和深度学习大模型的加持下,AI生成内容(AI Gen…

(七)文件——PHP

文章目录第七章 文件1 文件包含**1.1 include()函数****1.2 require()函数**2 文件的读取和写入**2.1 文件模式****2.2 文件读取****2.3 文件写入**3 文件上传3.1 创建表单3.2 创建脚本3.3 实例第七章 文件 1 文件包含 您可以在服务器执行PHP文件之前将其内容包含到另一个PHP…

支付宝"手机网站支付"主域名申请了,二级域名还要申请吗

微信商城小程序里可以用支付宝付款吗?当然可以了,不过需要去支付宝官方网站去申请一个接口,注意选对产品,支付宝提供了很多种接口,微信里要用到的支付宝付款属于“手机网站支付”这个产品,重要的事情说三遍…

一文讲解,Linux内核——内存管理(建议收藏)

一.内存的基础知识: 1.写程序到程序运行的过程: (1)编译:由编译程序将用户代码编译成若干个目标模块(把高级语言翻译成机器语言) (2)链接:由链接程序将编译…