通俗易懂的JS之Proxy
与掘金文章同步,地址:https://juejin.cn/post/6964398933229436935
什么是代理模式
引入一个现实生活中的案例
我们作为用户需要去如何评估一个房子的好坏、如何办理住房手续等一些列繁琐的事物吗?显然,用户肯定不愿意这样做。用户最关心的是结果,用户对房子提出需求以及提供对等价值的金钱就可以获得满意的房子,这就是结果。
那么谁为用户去解决一系列繁琐的买房过程呢?当然就是“房屋中介”了!房屋中介的作用就是在房地产开发经营与消费的供求市场中,为交易物体提供评估、交易、代理、咨询等服务及善后服务的机构。
结合案例理解代理模式的定义
代理模式为其他对象提供一种代理以控制对这个对象的访问。在某些情况下,一个对象不适合或者不能直接引用另一个对象,而代理对象可以在客户端和目标对象之间起到中介的作用。
结合上边的现实生活中的案例来理解这一段话,代理模式就是为其他用户提供一种代理,不让用户知道买房的过程,而用户应该关心的是如何获得满意的结果。代理所需要做的事情就是完成这一买房的过程。
什么是Proxy
Proxy用于修改某些操作的默认行为,在目标对象前架设一个
“拦截”层,外界对该对象的访问都必须先通过这一层拦截,因此提供了一种机制可以对外界的访问进行过滤和改写。——《ES6标准入门》- 第12章
Proxy支持的拦截操作有get(target, propKey, receiver)和set(target, propKey, value, receiver),对于可以设置但没有设置拦截的操作,则直接落在目标对象上,按照原先的方式产生结果。
- get实例方法:拦截对象属性的读取;
 - set实例方法:拦截对象属性的设置。
 
get(target, propKey, receiver)
定义一个person对象
var person = {
    name: "kongsam",
    age: 21,
    hobbies: [
        "看动漫",
        "骑行",
        "玩游戏"
    ]
}
现在实例化一个Proxy对象,来拦截外界对person的操作
var proxy = new Proxy(person, {
    get: function (target, property) {
          // 打印target和property,查看里面到底是什么。
          console.log("target = ", target);
          console.log("property = ", property);
          // 判断外界访问的对象属性是否存在于目标对象中。
          if (property in target) {
                return target[property];
          } else {
                // 如果外界访问的对象属性不存在与目标对象中,抛出异常。
                throw new ReferenceError('Property "' + property + '" 不存在。');
          }
    },
});
当我proxy.name时,由于person对象已经被该代理对象给代理了,并且该代理对象为person对象设置了一层拦截,就是所谓的拦截层,所以每当我通过该代理对象访问person中存在的属性时,都会调用get函数,因为get函数是拦截对象属性的读取的。
get: function (target, property) 中的两个参数target和property分别接收到的信息如图所示
上面说到,通过该代理对象访问person中存在的属性时,如果访问不存在的属性,会发生什么?
我又是做了什么样的工作,才导致访问不存在的属性时,它会抛出异常呢?
因为外界对该对象的访问都必须先通过一层拦截,而拦截的过程中提供了一种机制可以对外界的访问进行过滤和改写。
// 判断外界访问的对象属性是否存在于目标对象中。
if (property in target) {
    return target[property];
} else {
    // 如果外界访问的对象属性不存在与目标对象中,抛出异常。
    throw new ReferenceError('Property "' + property + '" 不存在。');
}
这里的if语句判断实际上就是我设置的一个机制,即对外界的访问进行过滤和改写。如果没有这种机制,访问不存在的属性只会返回undefined。
set(target, propKey, value, receiver)
有get就有对应的set,依旧是上面的person对象,这时我有个新需求,即修改age属性时,值不能超过150且是整数。
新增proxy对象中的set方法
var proxy = new Proxy(person, {
    set: function (target, property, value) {
          // 打印target、property和value,查看里面到底是什么。
          console.log("target = ", target);
          console.log("property = ", property);
          console.log("value = ", value);
          if (property === "age") {
                if (!Number.isInteger(value)) {
                  throw new TypeError("age的值不是整数!");
                }
                if (value > 150) {
                  throw new RangeError("age的值不能大于150!");
                }
          }
    },
});
当我执行proxy.age = 100时,set的三个参数分别接收到的信息如下图所示
set方法的作用是用于拦截某个属性的赋值操作,那么我如果对age的赋值操作不满足我刚刚提出的新需求,会发生什么?
很明显,会抛出异常。
总结
Proxy 就是一个拦截层,你给出要代理的对象,外界访问这个对象不是直接访问他的,而是访问这个Proxy的实例对象的。我们可以通过Proxy为外界访问进行过滤和改写,如赋值时需满足某些条件。
代理对象中还有许多的方法,如has、deleteProperty、ownKeys、getOwnPropertyDescriptor、defineProperty等等。这些都是用于拦截的方法,针对于不同的情况而出现的。
通俗易懂的JS之Proxy的更多相关文章
- ArcGIS JS 使用Proxy之 Printing Tools unable to connect to mapServer
		
ArcGIS JS使用Proxy.ashx将地图服务隐藏,并在微博服务器端增加了地图服务权限判断. Proxy.ashx做了如下设置, <serverUrl url="http://l ...
 - 关于vue.config.js 的 proxy 配置
		
关于vue.config.js 的 proxy 配置有的同学不怎么明白项目里面有的配置了 pathRewrite 地址重写,有的又没有进行配置?/* * proxy代理配置的说明 * *接口例子:/z ...
 - EXT.JS的PROXY放在哪里,STORE放在哪里,绝对是个技术活儿啊。
		
我理解的是,单独的STORE,会在应用程序开始时就加载, 而VIEWMODEL的STORE,会在VIEW加载时才开始加载. PROXY放在STORE,则会在调用这个STORE的VIEW才能请求服务器数 ...
 - arcgis js api proxy java 版本配置
		
<?xml version="1.0" encoding="utf-8" ?> <ProxyConfig allowedReferers=&q ...
 - 在 Node.js 上调用 WCF Web 服务
		
摘要:有时我们需要在WCF中做一些复杂数据处理和逻辑判断等,这时候就需要在NodeJS中调用WCF服务获取数据,这篇文件介绍如何在Node中调用WCF服务获取数据. Node项目中调用WCF服务获取数 ...
 - C# 使用 Proxy 代理请求资源
		
C# 使用 Proxy 请求资源,基于 HttpWebRequest 类 前言 这是上周在开发 C# 中使用 Proxy 代理时开发的一些思考和实践.主要需求是这样的,用户可以配置每次请求是否需要代理 ...
 - react proxy 报错
		
react项目中,package.json中proxy的配置如下 "proxy": { "/api/rjwl": { "target": & ...
 - webpack 4 的 proxy
		
第一种 接口有api的 setupProxy.js const proxy = require('http-proxy-middleware'); module.exports = function( ...
 - react 添加代理 proxy
		
react package.json中proxy的配置如下 "proxy": { "/api/rjwl": { "target": &quo ...
 
随机推荐
- C++覆盖,隐藏,重载
			
code[class*="language-"], pre[class*="language-"] { color: rgba(51, 51, 51, 1); ...
 - ASPOSE.Cells & ASPOSE.Words 操纵Excel和Word文档的 .NET Core 实例
			
Aspose.Total是Aspose公司旗下的最全的一套office文档管理方案,它提供的原生API可以对Word.Excel.PDF.Powerpoint.Outlook.CAD.图片.3D.ZI ...
 - Redis入门到放弃系列-redis数据类型
			
Redis数据类型? Redis 提供一些常用的数据类型:Strings.Lists.Sets.Sorted sets.Hashes.Arrays.Bitmap.Streams Strings(字符串 ...
 - 学《跟我一起写Makefile》笔记发博词
			
目录 笔记发博词 参考 笔记发博词 本系列笔记主要记录学了<跟我一起写Makefile>后的一些笔记 由于<跟我一起写Makefile>已经写得很详细了,所以我只是提取其中重要 ...
 - LevelDB 源码解析之 Random 随机数
			
GitHub: https://github.com/storagezhang Emai: debugzhang@163.com 华为云社区: https://bbs.huaweicloud.com/ ...
 - java例题 判断一个数能被几个9整除
			
有点懵,被几个9整除,我理解的是n=n/9能整除几次,代码如下: 1 /*45 [程序 45 被 9 整除] 2 题目:判断一个数能被几个 9 整除 3 */ 4 5 /*分析 6 * 1.用whil ...
 - 计算机体系结构——CH4 输入输出系统
			
计算机体系结构--CH4 输入输出系统 右键点击查看图像,查看清晰图像 X-mind 计算机体系结构--CH4 输入输出系统 输入输出原理 特点 实时性 与设备无关性 异步性 输入输出系统的组织方式 ...
 - Windows搭建Linux子系统(WSL)详细教程
			
介绍 WSL(windows下的Linux子系统) Windows Subsystem for Linux(简称WSL)是一个在Windows 10上能够运行原生Linux二进制可执行文件(ELF格式 ...
 - Dapr | 云原生的抽象与实现
			
引言 Dapr 是微软主导的云原生开源项目,2019年10月首次发布,到今年2月正式发布 V1.0 版本.在不到一年半的时间内,github star 数达到了 1.2 万,超过同期的 kuberne ...
 - 创建逻辑卷,格式化为xfs格式化,在线扩容
			
创建逻辑卷,并且格式化为xfs格式化好,然后在线扩容 删除逻辑卷组