Proxy与Reflect

Proxy

构造函数

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

语法:new Proxy(target, handler)

参数:

  • target:要使用 Proxy 包装的目标对象(可以是任何类型的对象,包括原生数组,函数,甚至另一个代理)
  • handler:一个通常以函数作为属性的对象,各属性中的函数分别定义了在执行各种操作时代理 p 的行为

方法

Proxy.revocable()

Proxy.revocable() 方法可以用来创建一个可撤销的代理对象。

语法:Proxy.revocable(target, handler)

  • target:将用 Proxy 封装的目标对象。可以是任何类型的对象,包括原生数组,函数,甚至可以是另外一个代理对象。
  • handler:一个对象,其属性是一批可选的函数,这些函数定义了对应的操作被执行时代理的行为。

handler 对象的方法

handler 对象是一个容纳一批特定属性的占位符对象。它包含有 Proxy 的各个捕获器(trap)。

所有的捕捉器是可选的。如果没有定义某个捕捉器,那么就会保留源对象的默认行为。

handler.get()

handler.get() 方法用于拦截对象的读取属性操作。

语法:

new Proxy(target, {get(target, property, receiver) {},
});

参数:

  • target:目标对象
  • property:被获取的属性名
  • receiver:Proxy 或者继承 Proxy 的对象

返回:返回任何值

该方法会拦截目标对象的以下操作:

  • 访问属性:proxy[foo] 和 proxy.bar
  • 访问原型链上的属性:Object.create(proxy)[foo]
  • Reflect.get()

如果违背了以下的约束,proxy 会抛出 TypeError:

  • 如果要访问的目标属性是不可写以及不可配置的,则返回的值必须与该目标属性的值相同
  • 如果要访问的目标属性没有配置访问方法,即 get 方法是 undefined 的,则返回值必须为 undefined

handler.set()

handler.set() 方法是设置属性值操作的捕获器。

语法:

new Proxy(target, {set(target, property, value, receiver) {}
});

参数:

  • target:目标对象
  • property:被获取的属性名
  • value:新属性值
  • receiver:Proxy 或者继承 Proxy 的对象

返回:返回一个布尔值

  • 返回 true 代表属性设置成功
  • 在严格模式下,如果 set() 方法返回 false,那么会抛出一个 TypeError 异常

该方法会拦截目标对象的以下操作:

  • 指定属性值:proxy[foo] = barproxy.foo = bar
  • 指定继承者的属性值:Object.create(proxy)[foo] = bar
  • Reflect.set()

如果违背以下的约束条件,proxy 会抛出一个 TypeError 异常:

  • 若目标属性是一个不可写及不可配置的数据属性,则不能改变它的值
  • 如果目标属性没有配置存储方法,即 [[Set]] 属性的是 undefined,则不能设置它的值
  • 在严格模式下,如果 set() 方法返回 false,那么也会抛出一个 TypeError 异常

handler.has()

handler.has() 方法是针对 in 操作符的代理方法。

语法:

new Proxy(target, {has(target, prop) {},
});

参数:

  • target:目标对象
  • prop:需要检查是否存在的属性

返回:返回一个 boolean 属性的值

这个钩子可以拦截下面这些操作:

  • 属性查询:foo in proxy
  • 继承属性查询:foo in Object.create(proxy)
  • with 检查: with(proxy) { (foo); }
  • Reflect.has()

如果违反了下面这些规则,proxy 将会抛出 TypeError:

  • 如果目标对象的某一属性本身不可被配置,则该属性不能够被代理隐藏。
  • 如果目标对象为不可扩展对象,则该对象的属性不能够被代理隐藏

handler.apply()

handler.apply() 方法用于拦截函数的调用。

语法:

new Proxy(target, {apply(target, thisArg, argumentsList) {},
});

参数:

  • target:目标对象(函数)
  • thisArg:被调用时的上下文对象
  • argumentsList:被调用时的参数数组

返回:返回任何值

该方法会拦截目标对象的以下操作:

  • proxy(...args)
  • Function.prototype.apply()Function.prototype.call()
  • Reflect.apply()

handler.construct()

handler.construct() 方法用于拦截 new 操作符。为了使 new 操作符在生成的 Proxy 对象上生效,用于初始化代理的目标对象自身必须具有 [[Construct]] 内部方法(即 new target 必须是有效的)。

语法:

new Proxy(target, {construct(target, argumentsList, newTarget) {},
});

参数:

  • target:目标对象
  • argumentsList:constructor 的参数列表
  • newTarget:最初被调用的构造函数,就上面的例子而言是 p

返回:返回一个对象

该拦截器可以拦截以下操作:

  • new proxy(...args)
  • Reflect.construct()

如果违反以下约定,代理将会抛出错误 TypeError:

  • 必须返回一个对象

handler.deleteProperty()

handler.deleteProperty() 方法用于拦截对对象属性的 delete 操作。

语法:

new Proxy(target, {deleteProperty(target, property) {},
});

参数:

  • target:目标对象
  • property:被获取的属性名

返回:返回一个 Boolean 类型的值,表示了该属性是否被成功删除

该方法会拦截以下操作:

  • 删除属性:delete proxy[foo]delete proxy.foo
  • Reflect.deleteProperty()

如果违背了以下不变量,proxy 将会抛出一个 TypeError:

  • 如果目标对象的属性是不可配置的,那么该属性不能被删除。

handler.ownKeys()

handler.ownKeys() 方法用于拦截 Reflect.ownKeys()

语法:

new Proxy(target, {ownKeys(target) {},
});

参数:

  • target:目标对象

返回:返回一个可枚举对象

该拦截器可以拦截以下操作::

  • Object.getOwnPropertyNames()
  • Object.getOwnPropertySymbols()
  • Object.keys()
  • Reflect.ownKeys()

如果违反了下面的约束,proxy 将抛出错误 TypeError:

  • ownKeys 的结果必须是一个数组
  • 数组的元素类型要么是一个 String ,要么是一个 Symbol
  • 结果列表必须包含目标对象的所有不可配置(non-configurable)、自有(own)属性的 key
  • 如果目标对象不可扩展,那么结果列表必须包含目标对象的所有自有(own)属性的 key,不能有其他值

handler.getPrototypeOf()

handler.getPrototypeOf() 是一个代理(Proxy)方法,当读取代理对象的原型时,该方法就会被调用。

语法:

new Proxy(target, {getPrototypeOf(target) {}
})

参数:

  • target:被代理的目标对象。

返回:返回一个对象或者 null

这个方法可以拦截以下操作:

  • Object.getPrototypeOf()
  • Reflect.getPrototypeOf()
  • Object.prototype.__proto__
  • Object.prototype.isPrototypeOf()
  • instanceof

如果遇到了下面情况,JS 引擎会抛出 TypeError 异常:

  • getPrototypeOf() 方法返回的不是对象也不是 null
  • 目标对象是不可扩展的,且 getPrototypeOf() 方法返回的原型不是目标对象本身的原型

handler.setPrototypeOf()

handler.setPrototypeOf() 方法主要用来拦截 Object.setPrototypeOf().

语法:

new Proxy(target, {setPrototypeOf(target, prototype) {}
})

参数:

  • target:被拦截目标对象
  • prototype:对象新原型或为 null

返回:如果成功修改了[[Prototype]],返回 true,否则返回 false

这个方法可以拦截以下操作:

  • Object.setPrototypeOf()
  • Reflect.setPrototypeOf()

如果遇到了下面情况,JS 引擎会抛出 TypeError 异常:

  • 如果 target 不可扩展,原型参数必须与 Object.getPrototypeOf(target) 的值相同

handler.isExtensible()

handler.isExtensible() 方法用于拦截对对象的 Object.isExtensible()

语法:

new Proxy(target, {isExtensible(target) {}
})

参数:

  • target:目标对象

返回:返回一个 Boolean 值或可转换成 Boolean 的值

这个方法可以拦截以下操作:

  • Object.isExtensible()
  • Reflect.isExtensible()

如果遇到了下面情况,JS 引擎会抛出 TypeError 异常:

  • Object.isExtensible(proxy) 必须同 Object.isExtensible(target) 返回相同值

handler.preventExtensions()

handler.preventExtensions() 方法用于设置对 Object.preventExtensions() 的拦截。

语法:

new Proxy(target, {preventExtensions(target) {}
})

参数:

  • target:所要拦截的目标对象

返回:返回一个布尔值

这个方法可以拦截以下操作:

  • Object.preventExtensions()
  • Reflect.preventExtensions()

如果遇到了下面情况,JS 引擎会抛出 TypeError 异常:

  • 如果目标对象是可扩展的,那么只能返回 false

handler.getOwnPropertyDescriptor()

handler.getOwnPropertyDescriptor() 方法是 Object.getOwnPropertyDescriptor() 的钩子。

语法:

new Proxy(target, {getOwnPropertyDescriptor(target, prop) {}
})

参数:

  • target:所要拦截的目标对象
  • prop:返回属性名称的描述

返回:返回一个 object 或 undefined

这个方法可以拦截以下操作:

  • Object.getOwnPropertyDescriptor()
  • Reflect.getOwnPropertyDescriptor()

如果下列不变量被违反,代理将抛出一个 TypeError

  • getOwnPropertyDescriptor 必须返回一个 object 或 undefined
  • 如果属性作为目标对象的不可配置的属性存在,则该属性无法报告为不存在。
  • 如果属性作为目标对象的属性存在,并且目标对象不可扩展,则该属性无法报告为不存在。
  • 如果属性不存在作为目标对象的属性,并且目标对象不可扩展,则不能将其报告为存在。
  • 属性不能被报告为不可配置,如果它不作为目标对象的自身属性存在,或者作为目标对象的可配置的属性存在。
  • Object.getOwnPropertyDescriptor(target)的结果可以使用 Object.defineProperty 应用于目标对象,也不会抛出异常。

handler.defineProperty()

handler.defineProperty() 用于拦截对象的 Object.defineProperty() 操作。

语法:

new Proxy(target, {defineProperty(target, property, descriptor) {}
})

参数:

  • target:目标对象
  • property:待检索其描述的属性名
  • descriptor:待定义或修改的属性的描述符

返回:返回 Boolean,表示定义该属性的操作成功与否

该方法会拦截目标对象的以下操作:

  • Object.defineProperty()
  • Reflect.defineProperty()
  • proxy.property='value'

如果违背了以下的不变量,proxy 会抛出 TypeError:

  • 如果目标对象不可扩展,将不能添加属性
  • 不能添加或者修改一个属性为不可配置的,如果它不作为一个目标对象的不可配置的属性存在的话
  • 如果目标对象存在一个对应的可配置属性,这个属性可能不会是不可配置的
  • 如果一个属性在目标对象中存在对应的属性,那么 Object.defineProperty(target, prop, descriptor) 将不会抛出异常
  • 在严格模式下,false 作为 handler.defineProperty 方法的返回值的话将会抛出 TypeError 异常

Reflect

Reflect 是一个内置的对象,它提供拦截 JavaScript 操作的方法。这些方法与 proxy.handler 的方法相同。

Reflect 不是一个函数对象,因此它是不可构造的。

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

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

相关文章

SQL必知必会读书笔记

文章目录 **不同的DB语法格式不尽相同**第一课 了解SQL术语 第二课 检索数据语法格式检索列检索唯一不同值限制结果(数量) 第三课 排序检索数据使用说明 第四课 过滤数据WHERE子句操作符 第五课 高级数据过滤1、组合WHERE子句2、IN操作符3、NOT操作符 第…

【数据结构与算法——TypeScript】哈希表

【数据结构与算法——TypeScript】 哈希表(HashTable) 哈希表介绍和特性 哈希表是一种非常重要的数据结构,但是很多学习编程的人一直搞不懂哈希表到底是如何实现的。 在这一章节中,我门就一点点来实现一个自己的哈希表。通过实现来理解哈希表背后的原理…

前后端交互开发模式yapi使用

接手一个项目组,采用前后端开发模式分离,经过一阵子了解后,发现存在前后端配合不顺畅的情况,存在如下两个问题, 一:没有接口协议,前端开发时先用占位符,等后端开发协议出来后替换,影响效率。 二:前端开发好了, 后端没开发好,前端只能等待后端开发好。 做为一个团队技…

记录uniapp 滚动后溢出显示空白的办法

写了一个横向滚动,超出可视区域图片空白,上下滚动页面可视区域图片显示,不可见区域滚动出来变成空白 错误css如下 width: 678rpx;height: 264rpx;background: #ffffff;border-radius: 16rpx;margin: 64rpx 18rpx 10rpx 18rpx;overflow-y: hid…

Zabbix网络拓扑配置

一、简介 网络拓扑功能是一项非常重要的功能,它可以直观展示网络设备主机状态及端口传输速率等指标信息,帮助运维人员快速发现和定位故障问题;Zabbix同样配备了强大的网络拓扑功能,如何使用Zabbix拓扑图功能创建一个公司网络拓扑…

11_Pulsar Adaptors适配器、kafka适配器、Spark适配器

2.3. Pulsar Adaptors适配器 2.3.1.kafka适配器 2.3.2.Spark适配器 2.3. Pulsar Adaptors适配器 2.3.1.kafka适配器 Pulsar 为使用 Apache Kafka Java 客户端 API 编写的应用程序提供了一个简单的解决方案。 在生产者中, 如果想不改变原有kafka的代码架构, 就切换到Pulsar的…

FreeRTOS通过消息队列实现串口命令解析(串口中断)

作者:Jack_G 时间:2023.08.08 版本:V1.0 上次修改时间: 环境: \quad \quad \quad \quad STM32Cube MX V6.8.1 \quad \quad \quad \quad STM32CubeH7 Firmware Package V1.11.0 / 04-Nov-2022 \quad \quad \quad \qu…

[SQL智慧航行者] - 用户购买商品推荐

话不多说, 先看数据表信息. 数据表信息: employee 表, 包含所有员工信息, 每个员工有其对应的 id, salary 和 departmentid. --------------------------------- | id | name | salary | departmentid | --------------------------------- | 1 | Joe | 70000 | 1 …

抖音的竞争对手?Meta计划人工智能聊天机器人增加社交媒体数量

在来自抖音的竞争中,Meta着眼于用户参与的下一个前沿。 报道,Meta正在开发一系列具有不同个性的人工智能聊天机器人,此举旨在增加用户在脸书和Instagram等社交平台上的参与度金融时报和边缘。这些聊天机器人被Meta staff称为“personas ”,将…

LabVIEW开发高压配电设备振动信号特征提取与模式识别

LabVIEW开发高压配电设备振动信号特征提取与模式识别 矿用高压配电设备是井下供电系统中的关键设备之一,肩负着井下供配电和供电安全的双重任务,其工作状态直接影响着井下供电系统的安全性和可靠性。机械故障占配电总故障的70%。因此,机械故…

代理模式及常见的3种代理类型对比

代理模式及常见的3种代理类型对比 代理模式代理模式分类静态代理JDK动态代理CGLIBFastclass机制 三种代理方式之间对比常见问题 代理模式 代理模式是一种设计模式,提供了对目标对象额外的访问方式,即通过代理对象访问目标对象,这样可以在不修…

嵌入式开发实用工具——QFSViewer

嵌入式开发实用工具——QFSViewer 介绍 今天给大家推荐个我个人业余时间开发的一个嵌入式开发实用工具——QFSViewer,这个工具主要是用来加载查看各种嵌入式常用的文件系统映像,目前支持JFSS2、Fat32、Fat16、Fat12、exFat、Ext2、Ext3、Ext4等文件系统…

用栈判断是否匹配

1 问题 写代码的时候用到的括号都是成双成对的出现,并且大小也相同。在集成编辑环境中,IDE就会为我们自己动检查括号是否匹配。那么为了避免在报错,如何判断是否有无括号不匹配? 2 方法 利用栈来实现这种功能。当遇见一个左括号&a…

【Linux命令行与Shell脚本编程】 第十七章 图形化桌面环境脚本编程

Linux命令行与Shell脚本编程 第十七章 图形化桌面环境脚本编程 文章目录 Linux命令行与Shell脚本编程七.图形化桌面环境脚本编程7.1.创建文本菜单7.1.1.创建菜单布局7.1.2.创建菜单逻辑7.1.3.整合脚本菜单7.1.4.使用select命令 7.2.创建文本窗口部件7.2.1.dialog软件包部件msg…

wpf 项目中使用 Prism + MaterialDesign

1.通过nuget安装MaterialDesign 2.通过nuget安装Prism 3.修改App.xmal <prism:PrismApplication x:Class"VisionMeasureGlue.App"xmlns"http://schemas.microsoft.com/winfx/2006/xaml/presentation"xmlns:x"http://schemas.microsoft.com/winfx/…

24华东交通软件工程837考研题库

1&#xff0e;Jackson设计方法是由英国的M&#xff0e;Jackson所提出的。它是一种面向( )的软件设 计方法。 A&#xff0e;对象 B&#xff0e;数据流 C&#xff0e;数据结构 D&#xff0e;控制结构 答案:C 2&#xff0e;软件设计中&#xff0c;Jackson方法是一种面向…

66 # form 数据格式化

实现一个 http 服务器 客户端会发送请求 GET POST 要处理不同的请求体的类型 表单格式&#xff08;formData a1&b2&#xff09;&#xff0c;可以直接通信不会出现跨域问题JSON &#xff08;"{"kaimo":"313"}"&#xff09;文件格式 &#x…

Android 项目导入高德SDK初次上手

文章目录 一、前置知识&#xff1a;二、学习目标三、学习资料四、操作过程1、创建空项目2、高德 SDK 环境接入2.1 获取高德 key2.2下载 SDK 并导入2.2.1、下载SDK 文件2.2.2、SDK 导入项目2.2.3、清单文件配置2.2.4、隐私权限 3、显示地图 一、前置知识&#xff1a; 1、Java 基…

数据结构----算法--分治,快速幂

数据结构----算法–分治,快速幂 一.分治 1.分治的概念 分治法&#xff1a;分而治之 将一个问题拆解成若干个解决方式完全相同的问题 满足分治的四个条件 1.问题难度随着数据规模缩小而降低 2.问题可拆分 3.子问题间相互独立 4.子问题的解可合并 2.二分查找(折半搜索)…

移动端自动化测试实战

UI自动化测试的价值 1、提升回归测试的效率 2、可以进行兼容性测试 UI 自动化测试应用场景 • 冒烟测试自动化&#xff1a;提测之前自动断言提测质量&#xff0c;提供准入参考。 • 功能测试自动化&#xff1a;辅助 QA 与测试工程师的快速验证。 • 验收测试自动化&#xf…