柳州做网站人员/媒体代发布
Proxy用于创建一个对象的代理,从而实现基本操作的拦截和自定义(如属性查找、赋值、枚举、函数调用等)
1.用法
Proxy
为 构造函数,用来生成 Proxy
实例
var proxy = new Proxy(target, handler)
参数
target
表示所要拦截的目标对象(任何类型的对象,包括原生数组,函数,甚至另一个代理))
handler
通常以函数作为属性的对象,各属性中的函数分别定义了在执行各种操作时代理 p
的行为
handler解析
关于handler
拦截属性,有如下:
- get(target,propKey,receiver):拦截对象属性的读取
- set(target,propKey,value,receiver):拦截对象属性的设置
- has(target,propKey):拦截
propKey in proxy
的操作,返回一个布尔值 - deleteProperty(target,propKey):拦截
delete proxy[propKey]
的操作,返回一个布尔值 - ownKeys(target):拦截
Object.keys(proxy)
、for...in
等循环,返回一个数组 - getOwnPropertyDescriptor(target, propKey):拦截
Object.getOwnPropertyDescriptor(proxy, propKey)
,返回属性的描述对象 - defineProperty(target, propKey, propDesc):拦截
Object.defineProperty(proxy, propKey, propDesc)
,返回一个布尔值 - preventExtensions(target):拦截
Object.preventExtensions(proxy)
,返回一个布尔值 - getPrototypeOf(target):拦截
Object.getPrototypeOf(proxy)
,返回一个对象 - isExtensible(target):拦截
Object.isExtensible(proxy)
,返回一个布尔值 - setPrototypeOf(target, proto):拦截
Object.setPrototypeOf(proxy, proto)
,返回一个布尔值 - apply(target, object, args):拦截 Proxy 实例作为函数调用的操作
- construct(target, args):拦截 Proxy 实例作为构造函数调用的操作
Reflect
若需要在Proxy
内部调用对象的默认行为,建议使用Reflect
,其是ES6
中操作对象而提供的新 API
基本特点:
- 只要
Proxy
对象具有的代理方法,Reflect
对象全部具有,以静态方法的形式存在 - 修改某些
Object
方法的返回结果,让其变得更合理(定义不存在属性行为的时候不报错而是返回false
) - 让
Object
操作都变成函数行为
下面我们介绍proxy
几种用法:
get()
get
接受三个参数,依次为目标对象、属性名和 proxy
实例本身,最后一个参数可选
var person = {name: "张三"
};var proxy = new Proxy(person, {get: function(target, propKey) {return Reflect.get(target,propKey)}
});proxy.name // "张三"
get
能够对数组增删改查进行拦截,下面是试下你数组读取负数的索引
function createArray(...elements) {let handler = {get(target, propKey, receiver) {let index = Number(propKey);if (index < 0) {propKey = String(target.length + index);}return Reflect.get(target, propKey, receiver);}};let target = [];target.push(...elements);return new Proxy(target, handler);
}let arr = createArray('a', 'b', 'c');
arr[-1] // c
注意:如果一个属性不可配置(configurable)且不可写(writable),则 Proxy 不能修改该属性,否则会报错
const target = Object.defineProperties({}, {foo: {value: 123,writable: false,configurable: false},
});const handler = {get(target, propKey) {return 'abc';}
};const proxy = new Proxy(target, handler);proxy.foo
// TypeError: Invariant check failed
set()
set
方法用来拦截某个属性的赋值操作,可以接受四个参数,依次为目标对象、属性名、属性值和 Proxy
实例本身
假定Person
对象有一个age
属性,该属性应该是一个不大于 200 的整数,那么可以使用Proxy
保证age
的属性值符合要求
let validator = {set: function(obj, prop, value) {if (prop === 'age') {if (!Number.isInteger(value)) {throw new TypeError('The age is not an integer');}if (value > 200) {throw new RangeError('The age seems invalid');}}// 对于满足条件的 age 属性以及其他属性,直接保存obj[prop] = value;}
};let person = new Proxy({}, validator);person.age = 100;person.age // 100
person.age = 'young' // 报错
person.age = 300 // 报错
如果目标对象自身的某个属性,不可写且不可配置,那么set
方法将不起作用
const obj = {};
Object.defineProperty(obj, 'foo', {value: 'bar',writable: false,
});const handler = {set: function(obj, prop, value, receiver) {obj[prop] = 'baz';}
};const proxy = new Proxy(obj, handler);
proxy.foo = 'baz';
proxy.foo // "bar"
注意,严格模式下,set
代理如果没有返回true
,就会报错
'use strict';
const handler = {set: function(obj, prop, value, receiver) {obj[prop] = receiver;// 无论有没有下面这一行,都会报错return false;}
};
const proxy = new Proxy({}, handler);
proxy.foo = 'bar';
// TypeError: 'set' on proxy: trap returned falsish for property 'foo'
deleteProperty()
deleteProperty
方法用于拦截delete
操作,如果这个方法抛出错误或者返回false
,当前属性就无法被delete
命令删除
var handler = {deleteProperty (target, key) {invariant(key, 'delete');Reflect.deleteProperty(target,key)return true;}
};
function invariant (key, action) {if (key[0] === '_') {throw new Error(`无法删除私有属性`);}
}var target = { _prop: 'foo' };
var proxy = new Proxy(target, handler);
delete proxy._prop
// Error: 无法删除私有属性
注意,目标对象自身的不可配置(configurable)的属性,不能被deleteProperty
方法删除,否则报错
取消代理
Proxy.revocable(target, handler);
2.使用的场景
Proxy
其功能非常类似于设计模式中的代理模式,常用功能如下:
- 拦截和监视外部对对象的访问
- 降低函数或类的复杂度
- 在复杂操作前对操作进行校验或对所需资源进行管理
使用 Proxy
保障数据类型的准确性
let numericDataStore = { count: 0, amount: 1234, total: 14 };
numericDataStore = new Proxy(numericDataStore, {set(target, key, value, proxy) {if (typeof value !== 'number') {throw Error("属性只能是number类型");}return Reflect.set(target, key, value, proxy);}
});numericDataStore.count = "foo"
// Error: 属性只能是number类型numericDataStore.count = 333
// 赋值成功
声明了一个私有的 apiKey
,便于 api
这个对象内部的方法调用,但不希望从外部也能够访问 api._apiKey
let api = {_apiKey: '123abc456def',getUsers: function(){ },getUser: function(userId){ },setUser: function(userId, config){ }
};
const RESTRICTED = ['_apiKey'];
api = new Proxy(api, {get(target, key, proxy) {if(RESTRICTED.indexOf(key) > -1) {throw Error(`${key} 不可访问.`);} return Reflect.get(target, key, proxy);},set(target, key, value, proxy) {if(RESTRICTED.indexOf(key) > -1) {throw Error(`${key} 不可修改`);} return Reflect.get(target, key, value, proxy);}
});console.log(api._apiKey)
api._apiKey = '987654321'
// 上述都抛出错误
还能通过使用Proxy
实现观察者模式
观察者模式(Observer mode)指的是函数自动观察数据对象,一旦对象有变化,函数就会自动执行
observable
函数返回一个原始对象的 Proxy
代理,拦截赋值操作,触发充当观察者的各个函数
const queuedObservers = new Set();const observe = fn => queuedObservers.add(fn);
const observable = obj => new Proxy(obj, {set});function set(target, key, value, receiver) {const result = Reflect.set(target, key, value, receiver);queuedObservers.forEach(observer => observer());return result;
}
观察者函数都放进Set
集合,当修改obj
的值,在会set
函数中拦截,自动执行Set
所有的观察者
相关文章:

Vue3 中的 Proxy--读懂ES6中的Proxy
Proxy用于创建一个对象的代理,从而实现基本操作的拦截和自定义(如属性查找、赋值、枚举、函数调用等) 1.用法 Proxy为 构造函数,用来生成 Proxy实例 var proxy new Proxy(target, handler)参数 target表示所要拦截的目标对象…...

zk_dubbo
图灵面试笔记 zk dubbo spi dubbo 文章 dubbo与spring整合之Service、Reference注解处理过程 JAVA备忘录...

Windows 安全基础——NetBIOS篇
Windows 安全基础——NetBIOS篇 1. NetBIOS简介 NetBIOS(Network Basic Input/Output System, 网络基本输入输出系统)是一种接入服务网络的接口标准。主机系统通过WINS服务、广播及lmhosts文件多种模式,把NetBIOS名解析对应的IP地址…...

【基础知识】Hadoop生态系统
Hadoop是一个开源的分布式计算框架,主要用于大数据的存储和处理,即一个包含多种组件的综合分布式系统,组件相互协作完成从数据存储到计算分析的完整功能。 关键词——容灾 主从结构、多副本 主要特点 分布式存储 - Hadoop采用HDFS文件系统,可以将大数据分布式存…...

[Linux] LAMP架构
一、LAMP架构架构的概述 LAMP 架构是一种流行的 Web 应用程序架构,它的名称是由四个主要组件的首字母组成的: Linux(操作系统): 作为操作系统,Linux 提供了服务器的基础。它负责处理硬件资源、文件系统管理…...

HPM5300系列--第二篇 Visual Studio Code开发环境以及多种调试器调试模式
一、目的 在博文《HPM5300系列--第一篇 命令行开发调试环境搭建》、《HPM6750系列--第四篇 搭建Visual Studio Code开发调试环境》中我们介绍了命令行方式开发环境,也介绍了HPM6750evkmini开发板如何使用Visual Studio Code进行开发调试(其中调试方式使用…...

LeetCode2697. Lexicographically Smallest Palindrome
文章目录 一、题目二、题解 一、题目 You are given a string s consisting of lowercase English letters, and you are allowed to perform operations on it. In one operation, you can replace a character in s with another lowercase English letter. Your task is t…...
Leetcode 40 组合总和 II
题意理解: 每个数字在每个组合中只能使用 一次 数字可以重复——>难点(如何去重) 每个组合和target 求组合,对合限制,考虑回溯的方法。——将其抽象为树结构。 树的宽度——分支大小 树的深度——最…...

智慧灯杆技术应用分析
智慧灯杆是指在传统灯杆的基础上,通过集成多种先进技术实现城市智能化管理的灯杆。智慧灯杆技术应用的分析如下: 照明功能:智慧灯杆可以实现智能调光、时段控制等功能,根据不同的需求自动调节照明亮度,提高照明效果&am…...

手动搭建koa+ts项目框架(ts项目实现开发阶段实时查看)
文章目录 前言优化脚本如有启发,可点赞收藏哟~ 前言 上篇文章记录了手动简单搭建 koats项目步骤 虽然可以直接编译后并开启服务,但如果修改./src内的文件,没法实时编译 以下介绍使用其他方法实现实时效果 优化脚本 咱使用以下依赖可实现边写…...

在Nexus上配置Docker镜像仓库
现在Docker镜像的工具已不少了,只是在Java老牌又持久的工具Nexus上配置本地Docker仓库镜像是一件即有情怀又充份利用资源的事情。 Nexus支持多种仓库类型,例如:maven、npm、docker等。 安装Nexus (略) Docker镜像配…...

深入理解C语言的函数参数
1、一个简单的函数 int Add(int x, int y) {return x y; }int main() {printf("%d", Add(2, 3, 4, 5, 6));return 0; } 这一段足够简单的代码,闭眼都能知道运行结果会在屏幕上打印 5 。那编译器是怎么处理后面的 4、5、6 ? 我们再看看这个函…...

【C++】策略模式
目录 一、简介1. 含义2. 特点 二、实现1. 策略接口(Strategy Interface)2. 具体策略类(Concrete Strategies)3. 上下文类(Context)4. 使用策略模式 三、总结如果这篇文章对你有所帮助,渴望获得你…...

什么时候使用匿名类,匿名类解决了什么问题?为什么需要匿名类 ?
匿名类通常在以下场景下使用: 一次性使用: 当你需要创建一个类的实例,但该类只在一个地方使用,而不打算在其他地方重复使用时,可以考虑使用匿名类。 简化代码: 当创建一个小型的、一次性的类会让代码更简洁…...

怎么让gpt帮忙改文章 (1) 快码论文
大家好,今天来聊聊怎么让gpt帮忙改文章 (1),希望能给大家提供一点参考。 以下是针对论文重复率高的情况,提供一些修改建议和技巧: 怎么让GPT帮忙改文章 一、背景介绍 随着人工智能的发展,自然语言处理技术已经成为了许…...

Android源码下载流程
1.使用repo方式: https://github.com/jeanboydev/Android-ReadTheFuckingSourceCode/blob/master/article/android/framework/Android-Windows%E7%8E%AF%E5%A2%83%E4%B8%8B%E8%BD%BD%E6%BA%90%E7%A0%81.md 2.使用git方式: Windows 环境下载 Android 源…...

ArrayList与顺序表(带完整实例)
【本节目标】 1. 线性表 2. 顺序表 3. ArrayList的简介 4. ArrayList使用 5. ArrayList的扩容机制 6. 扑克牌 1.线性表 线性表(linear list)是n个具有相同特性的数据元素的有限序列。 线性表是一种在实际中广泛使用的数据结构,常见的线性表…...

智能冶钢厂环境监控与设备控制系统(边缘物联网网关)
目录 1、项目背景 2、项目功能介绍 3、模块框架 3.1 架构框图 3.2 架构介绍 4、系统组成与工作原理 4.1 数据采集 4.2 指令控制 4.3 其他模块 4.3.1 网页、qt视频流 4.3.2 qt搜索进程 5、成果呈现 6、问题解决 7、项目总结 1、项目背景 这个项目的背景是钢铁行业的…...

【Python】conda镜像配置,.condarc文件详解,channel镜像
1. conda 环境 安装miniconda即可,Miniconda 安装包可以到 http://mirrors.aliyun.com/anaconda/miniconda/ 下载。 .condarc是conda 应用程序的配置文件,在用户家目录(windows:C:\users\username\),用于…...

实战章节:在Linux上部署各类软件
详细资料见文章的资源绑定 一、前言 1.1 为什么学习各类软件在Linux上的部署 在前面,我们学习了许多的Linux命令和高级技巧,这些知识点比较零散,同学们跟随着课程的内容进行练习虽然可以基础掌握这些命令和技巧的使用,但是并没…...

铭飞CMS list 接口 SQL注入漏洞复现
0x01 产品简介 铭飞CMS是一款基于java开发的一套轻量级开源内容管理系统,铭飞CMS简洁、安全、开源、免费,可运行在Linux、Windows、MacOSX、Solaris等各种平台上,专注为公司企业、个人站长快速建站提供解决方案 0x02 漏洞概述 铭飞CMS在5.2.10版本以前list 接口处存在sql注入…...

Linux指令初始
1.ls指令 语法 : ls [ 选项 ][ 目录或文件 ] 功能 :对于目录,该命令列出该目录下的所有子目录与文件。对于文件,将列出文件名以及其他信息。 ls 常用:-a 列出目录下的所有文件,包括以 . 开头的隐含文件。 …...

Nginx命令---启动nginx
介绍 使用命令启动nginx。 命令 nginx目录/bin/nginx...

【UE5】监控摄像头效果(下)
目录 效果 步骤 一、多摄像机视角切换 二、摄像头自动旋转巡视 三、摄像头跟踪拍摄 效果 步骤 一、多摄像机视角切换 1. 打开玩家控制器“MyPlayerController”,添加一个变量,命名为“BP_SecurityCameraArray”,类型为“BP_SecurityCa…...

binkw32.dll丢失怎么办?这5个方法都可以解决binkw32.dll丢失问题
binkw32.dll文件是什么? binkw32.dll是一个动态链接库文件,它是Windows操作系统中的一个重要组件。它包含了许多用于处理多媒体文件的函数和资源,如视频、音频等。当我们在电脑上打开或播放某些多媒体文件时,系统会调用binkw32.d…...

C语言-每日刷题练习
[蓝桥杯 2013 省 B] 翻硬币 题目背景 小明正在玩一个“翻硬币”的游戏。 题目描述 桌上放着排成一排的若干硬币。我们用 * 表示正面,用 o 表示反面(是小写字母,不是零),比如可能情形是 **oo***oooo,如果…...

Qt设置类似于qq登录页面(ikun)
头文件 #ifndef WIDGET_H #define WIDGET_H#include <QWidget> #include <QWindow> #include <QIcon> #include <QLabel> #include <QMovie> #include <QLineEdit> #include <QPushButton>QT_BEGIN_NAMESPACE namespace Ui { class…...

Qt 如何使用VTK显示点云
开发环境 ubuntu 20.04 VTK 8.2 编译VTK 下载源码 git clone --recursive https://gitlab.kitware.com/vtk/vtk.git 使用版本管理工具,切换版本到8.2 更改编译选项,这里使用cmake-gui进行配置 1、编译类型修改为Release 2、安装路径可以设置…...

Ganache结合内网穿透实现远程或不同局域网进行连接访问
文章目录 前言1. 安装Ganache2. 安装cpolar3. 创建公网地址4. 公网访问连接5. 固定公网地址 前言 Ganache 是DApp的测试网络,提供图形化界面,log日志等;智能合约部署时需要连接测试网络。 Ganache 是一个运行在本地测试的网络,通过结合cpol…...

Qt槽函数不响应不执行的一种原因:ui提升导致重名
背景: 一个包含了组件提升的ui,有个按钮的槽函数就是不响应,于是找原因。 分析: 槽函数的对应一是通过connect函数绑定信号,二是on_XXX_signal的命名方式。界面上部件的槽函数通常是第二种。 我反复确认细节&#…...