面试题:Proxy 相较于 Object.defineProperty 有什么优势?

面试题:Proxy 相较于 Object.defineProperty 有什么优势?

Object.defineProperty 详解

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

  • 功能:在一个对象上定义一个新属性修改其现有属性,并返回此对象

  • 参数

    • obj 要定义或修改属性的对象

    • prop 字符串或 Symbol,指定要定义或修改的属性键

    • descriptor 对象,指定要定义或修改的属性的描述符

      通过 descriptor,可以设置 prop 指定的属性值,gettersetter 等等特性。默认情况下,Object.defineProperty 添加的属性是不可写、不可枚举和不可配置的

  • 属性描述符(descriptor)的语法descriptor 有两种类型,数据描述符和访问器描述符,其只能是这两种类型之一。根据传入的属性描述符类型不同,给对象中定义或修改的属性的特性也将有所不同。因此,属性也可以分为数据属性和访问器属性

    因为 descriptor 是一个对象,因此有一系列可选的配置项。有些配置项是数据描述符特有的,有些配置项是访问器描述符特有的,有些配置项则是二者共享使用的。根据是否存在特有配置项,从而可以判断当前属性描述符的类型。注意,一个属性描述符中不能同时拥有两种类型的特有配置项

    适用情况配置取值描述默认值
    数据/访问器描述符configurabletrue/false该配置取值为 false 时,
    ①属性类型不可更改(数据属性、访问器属性)
    ②属性不可被删除
    ③ 属性描述符的配置项不可更改(特例,对于可写的数据属性,可以修改其数据描述符的 valuewritable
    否则:TypeError
    false
    数据/访问器描述符enumerabletrue/false该配置取值为 true 时,属性可以在对象的属性枚举中出现。(如 for...inObject.keys() 等)false
    数据描述符value任何有效的 JavaScript 值数据属性值undefined
    数据描述符writabletrue/false该配置取值为 true 时,属性可写(即可以使用赋值运算符 = 更改属性值)false
    访问器描述符get属性 getter 函数访问属性时,会不带参调用该函数,返回值被作为该属性的值undefined
    访问器描述符set属性 setter 函数当给属性赋值时,会调用该函数,并携带一个参数(表示要赋给属性的值)undefined

    注意事项:

    • getset 配置项对应的函数中的 this 不一定是属性所在对象,而是通过该属性访问的对象(由于继承关系的存在,当子对象访问父对象的 gettersetter 函数时,其中 this 指向子对象)。

      let parent = Object.defineProperty({}, "self", {get() {return this;}
      });let child = Object.create(parent);console.log(child.self === child); // true
      console.log(child.self === parent); // false
      console.log(parent.self === child); // false
      console.log(parent.self === parent); // true
      
    • 如果属性描述符没有包含任何特有配置项valuewritablegetset),此时该属性描述符被视作数据描述符

    • 如果属性描述符同时包含两种类型的特有配置项,则会抛出异常

    • 因为判断属性描述符是数据描述符还是访问器描述符时,常需要参考其中的属性,但是属性描述符其原型上的属性也会被考虑在内,这有可能会带来潜在问题,有以下两种解决方式。

      • 方式一:创建一个原型为 null 的属性描述符 const descriptor = Object.create(null);

      • 方式二:冻结 Object 原型对象 (Object.freeze || Object)(Object.prototype);

        Object.freeze 方法用于冻结一个对象,从而 ①不能向对象中添加新属性 ②不能删除对象中已有属性 ③不能修改对象中已有属性 ④ 不可有改对象的原型

Proxy 详解

  • 语法const p = new Proxy(target, handler)

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

  • 参数

    • target被代理的对象,可以是任何类型的对象(包含原生数组、函数、甚至代理)。
    • handler对象,其中的属性通常是函数,用于自定义代理 p各种操作所对应的具体的执行逻辑
  • 处理器对象(handler)的语法handler 中定义了一批特定属性,取值通常为函数,称之为捕获器trap)。

    配置项描述触发条件
    getPrototypeOf()Object.getPrototypeOf() 方法的捕捉器。当读取代理对象的原型时,该方法调用。如果该方法返回的不是对象也不是 null,则会报错 TypeErrorhandler.getPrototypeOf()
    setPrototypeOf()Object.setPrototypeOf() 方法的捕捉器。成功修改原型则返回 true,否则 falsehandler.setPrototypeOf()
    isExtensible()Object.isExtensible() 方法的捕捉器。handler.isExtensible()
    preventExtensions() Object.preventExtensions() 方法的捕捉器。handler.preventExtensions()
    getOwnPropertyDescriptor()Object.getOwnPropertyDescriptor() 方法的捕捉器。handler.getOwnPropertyDescriptor()
    defineProperty()Object.defineProperty()方法的捕捉器。handler.defineProperty()
    has()in 操作符的捕捉器。handler.has()
    get()属性读取操作的捕捉器。handler.get()
    set()属性设置操作的捕捉器。handler.set()
    deleteProperty()delete 操作符的捕捉器。handler.deleteProperty()
    ownKeys()Object.getOwnPropertyNames() 方法和 Object.getOwnPropertySymbols() 方法的捕捉器。handler.ownKeys()
    apply()函数调用操作的捕捉器。handler.apply()
    construct()new 操作符的捕捉器。handler.construct()

Proxy 相较于 Object.defineProperty 的优势

通过上边的介绍,可以看出 Proxy 有以下几点优势

  • 拦截范围更广Proxy 支持属性访问、修改、删除、枚举、原型操作、对象构造、方法调用、属性存在性检测、获取属性描述符、定义属性、in 操作符等的拦截。而 Object.defineProperty 只能拦截属性访问、修改。
  • 拦截实现更简单Proxy 可以直接拦截整个对象。而 Object.defineProperty 只能对单个属性进行拦截,如果要拦截整个对象,则需要在对象上逐个进行属性拦截。
  • 可撤销的拦截Proxy.revocable() 方法可以创建一个可撤销的代理对象。而 Object.defineProperty 一旦对属性进行了定义,就无法撤销。
  • 支持对数组的全方位拦截Proxyset 捕获器可以捕捉数组的任何操作,包含通过索引修改数组元素,通过数组方法修改数组元素,以及数组长度的变化。但是 Object.defineProperty 则无法实现。

REFERENCES

https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/Object/defineProperty

https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/Proxy

https://juejin.cn/post/7275551128854560779

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

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

相关文章

界面控件Telerik UI for WPF中文教程 - 用RadSvgImage升级应用程序UI

Telerik UI for WPF拥有超过100个控件来创建美观、高性能的桌面应用程序,同时还能快速构建企业级办公WPF应用程序。UI for WPF支持MVVM、触摸等,创建的应用程序可靠且结构良好,非常容易维护,其直观的API将无缝地集成Visual Studio…

笔记-Python中的struct模块

了解c语言的人,一定会知道struct结构体在c语言中的作用,它定义了一种结构,里面包含不同类型的数据(int,char,bool等等),方便对某一结构对象进行处理。而在网络通信当中,大多传递的数据是以二进制流(binary …

ADB命令来捕获设备屏幕快照和发送鼠标事件来实现抓取公众号文章

ADB命令来捕获设备屏幕和发送鼠标事件来实现抓取公众号文章 现在公众号需要登陆账号才能看到评论内容。登陆要账号的密码等,token还会过期。 现在的很多小程序进行了加密,那是否有方案可以抓取小程序或公众号的数据呢? 解决方案: …

【简报】VITA 74 (VNX)B

1 为什么向AMSAT社区提及VPX / VNX 1.1VPX是包括卫星在内的最新一代军用车辆增长最快的标准 VITA 65 – 面向地面车辆的 OpenVPX文献检索将揭示在许多商业和军事坚固型系统应用中的广泛应用VITA 78 – AFRL和工业界正在开发用于卫星的“SpaceVPX”和“Space VPX Lite” 1.2 …

R语言数据分析15-xgboost模型预测

XGBoost模型预测的主要大致思路: 1. 数据准备 首先,需要准备数据。这包括数据的读取、预处理和分割。数据应该包括特征和目标变量。 步骤: 读取数据:从CSV文件或其他数据源读取数据。数据清理:处理缺失值、异常值等…

AWS Load Balancer Controller 实践

背景 通过编写K8S的Ingress 然后能自动创建 aws的LB 作用 控制器监视 Kubernetes Ingress 或 Service 资源。作为响应,它会创建相应的 AWS 弹性负载均衡资源。您可以通过对 Kubernetes 资源应用注释来配置负载均衡器的特定行为。例如,您可以使用注释将 AWS 安全组附加到负…

人工智能_机器学习097_PCA数据降维算法_数据去中心化_特征值_特征向量_EVD特征值分解原来和代码实现---人工智能工作笔记0222

降维算法的原理,一会咱们再看,现在先看一下,算法 可以看到PCA算法的,原理和过程,我们先看一下代码 为了说明PCA原理,这里,我们,先来计算一下X的方差,可以看到 先把数据进行去中心化,也就是用数据,减去数据的平均值. B = X-X.mean(axis=0) 这段代码是用于计算矩阵X的每一列减去该…

websockets怎么工作的呢?

WebSockets是一种在单个TCP连接上进行全双工通信的协议,使得客户端和服务器之间的数据交换变得更加简单,并允许服务端主动向客户端推送数据。下面是WebSockets的工作原理: 1. **握手阶段**: - 客户端发起一个HTTP请求到服务器&…

react+vite创建

要在本地初始化一个结合了React和Vite的项目,你可以遵循以下步骤: 1、安装Node.js: 确保你的机器上已安装了Node.js。如果未安装,请前往Node.js官网下载并安装。 2、使用终端或命令提示符: 打开你的终端(…

测试工程师经常使用的Python中的库,以及对应常用的函数

os (操作系统接口) 该库提供了许多与操作系统交互的函数,如文件处理、目录操作、进程管理等。 常用功能包括: os.name: 获取操作系统的名称。 os.path: 用于操作文件路径的模块,如os.path.join拼接路径。 os.mkdir: 创建目录。 os.remove: 删…

EE trade:通货膨胀对老百姓意味着什么

通货膨胀,是经济领域中的一个常见现象,对社会各阶层尤其是普通老百姓的生活产生了深远影响。理解通货膨胀对老百姓的真实含义,可以帮助我们更好地应对日常生活的变化与挑战。 1. 生活成本的上升 最直接的影响体现在生活成本上。通货膨胀会导致…

Linux操作系统:Redis在虚拟环境下的安装与部署

Redis下载方法 最近部署项目的时候用到了Redis,自己在安装的时候也碰到了一些列问题最终安装成功,记录一下自己的安装历程。前期准备: 服务器Linux版本:Centos8.4 64位(http://isoredirect.centos.org/centos/8/isos/…

TS设置接收的形参类型

在我们使用pinia时会接受参数&#xff0c;一般来说是传递两个参数 setGlobalState(...args: ObjToKeyValArray<GlobalState>) {this.$patch({ [args[0]]: args[1] }); } 例如此时传递的是globalStore.setGlobalState("token", "123"); 那么此时的…

python姿态识别+Tensflow1.12+pyqt5+UI

python姿态识别Tensflow1.12pyqt5UI import datetimefrom PyQt5.QtCore import QCoreApplication from PyQt5.QtWidgets import QMainWindow, QApplication, QFileDialog from vedio import vediofrom HumanPoseRec import Ui_MainWindow from PyQt5 import QtCore, QtGui, Qt…

如何使用Python提取Excel中固定单元格的内容

正文共&#xff1a;1234 字 31 图&#xff0c;预估阅读时间&#xff1a;1 分钟 之前转载了颜总的Python环境搭建文章&#xff08;Python办公自动化—环境搭建&#xff09;&#xff0c;很久过去了&#xff0c;颜总也没有再更新。现在我有一个需求&#xff0c;就是我手上有大量格…

Android Studio 下载 | 安装 | 下载 SDK | 中文插件 | 卸载

文章目录 下载安装包安装下载 SDK中文插件卸载 下载安装包 下载 Android Studio 和应用工具 - Android 开发者 | Android Developers 点击下载 Android Studio。 在协议最下方勾选同意&#xff08;第一次用最好还是看一眼&#xff09;&#xff0c;再点击 Dowload Android Stu…

JS 转化中文首字母拼音

引入 chinapy.js文件下载地址 链接&#xff1a;百度云连接 提取码&#xff1a;zrjk import { makePy } from /utils/chinapy; let chinaPyName makePy(黄飞鸿) console.log(chinaPyName) // hfh

css文字超出元素省略,单行、多行省略

通用CSS .box {width: 500px;border: 1px solid red;padding: 10px;line-height: 24px;} 1.单行省略 .singe-line {text-overflow: ellipsis;overflow: hidden;word-break: break-all;white-space: nowrap;}<p>单行省略</p><div class"singe-line box&qu…

选择核密度估计带宽LSCV与DPI方法对比

最小二乘交叉验证&#xff08;Least Squares Cross-Validation, LSCV&#xff09;和直接插入法&#xff08;Direct Plug-in, DPI&#xff09;是两种常用于选择核密度估计带宽的方法。 原理与定义 最小二乘交叉验证&#xff08;LSCV&#xff09; 原理&#xff1a;通过交叉验证…

二叉树的中序遍历-力扣

二叉树的中序遍历&#xff0c;指首先遍历左节点&#xff0c;然后遍历中间节点&#xff0c;最后遍历右节点&#xff0c;按照这个顺序进行递归即可。 /*** Definition for a binary tree node.* struct TreeNode {* int val;* TreeNode *left;* TreeNode *right;* …