与掘金文章同步,地址:https://juejin.cn/post/6964398933229436935

什么是代理模式

引入一个现实生活中的案例

我们作为用户需要去如何评估一个房子的好坏、如何办理住房手续等一些列繁琐的事物吗?显然,用户肯定不愿意这样做。用户最关心的是结果,用户对房子提出需求以及提供对等价值的金钱就可以获得满意的房子,这就是结果。

那么谁为用户去解决一系列繁琐的买房过程呢?当然就是“房屋中介”了!房屋中介的作用就是在房地产开发经营与消费的供求市场中,为交易物体提供评估、交易、代理、咨询等服务及善后服务的机构。

结合案例理解代理模式的定义

代理模式为其他对象提供一种代理以控制对这个对象的访问。在某些情况下,一个对象不适合或者不能直接引用另一个对象,而代理对象可以在客户端和目标对象之间起到中介的作用。

结合上边的现实生活中的案例来理解这一段话,代理模式就是为其他用户提供一种代理,不让用户知道买房的过程,而用户应该关心的是如何获得满意的结果。代理所需要做的事情就是完成这一买房的过程

什么是Proxy

Proxy用于修改某些操作的默认行为,在目标对象前架设一个“拦截”层,外界对该对象的访问都必须先通过这一层拦截,因此提供了一种机制可以对外界的访问进行过滤和改写。——《ES6标准入门》- 第12章

Proxy支持的拦截操作有get(target, propKey, receiver)和set(target, propKey, value, receiver),对于可以设置但没有设置拦截的操作,则直接落在目标对象上,按照原先的方式产生结果。

  1. get实例方法:拦截对象属性的读取;
  2. 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的更多相关文章

  1. ArcGIS JS 使用Proxy之 Printing Tools unable to connect to mapServer

    ArcGIS JS使用Proxy.ashx将地图服务隐藏,并在微博服务器端增加了地图服务权限判断. Proxy.ashx做了如下设置, <serverUrl url="http://l ...

  2. 关于vue.config.js 的 proxy 配置

    关于vue.config.js 的 proxy 配置有的同学不怎么明白项目里面有的配置了 pathRewrite 地址重写,有的又没有进行配置?/* * proxy代理配置的说明 * *接口例子:/z ...

  3. EXT.JS的PROXY放在哪里,STORE放在哪里,绝对是个技术活儿啊。

    我理解的是,单独的STORE,会在应用程序开始时就加载, 而VIEWMODEL的STORE,会在VIEW加载时才开始加载. PROXY放在STORE,则会在调用这个STORE的VIEW才能请求服务器数 ...

  4. arcgis js api proxy java 版本配置

    <?xml version="1.0" encoding="utf-8" ?> <ProxyConfig allowedReferers=&q ...

  5. 在 Node.js 上调用 WCF Web 服务

    摘要:有时我们需要在WCF中做一些复杂数据处理和逻辑判断等,这时候就需要在NodeJS中调用WCF服务获取数据,这篇文件介绍如何在Node中调用WCF服务获取数据. Node项目中调用WCF服务获取数 ...

  6. C# 使用 Proxy 代理请求资源

    C# 使用 Proxy 请求资源,基于 HttpWebRequest 类 前言 这是上周在开发 C# 中使用 Proxy 代理时开发的一些思考和实践.主要需求是这样的,用户可以配置每次请求是否需要代理 ...

  7. react proxy 报错

    react项目中,package.json中proxy的配置如下 "proxy": { "/api/rjwl": { "target": & ...

  8. webpack 4 的 proxy

    第一种 接口有api的 setupProxy.js const proxy = require('http-proxy-middleware'); module.exports = function( ...

  9. react 添加代理 proxy

    react package.json中proxy的配置如下 "proxy": { "/api/rjwl": { "target": &quo ...

随机推荐

  1. 竖式问题(JAVA语言)

    package 第三章; import java.util.Scanner; public class 竖式问题 { public static void main(String[] args) { ...

  2. 《逆向工程核心原理》——DLL注入与卸载

    利用CreateRemoteThread #include <iostream> #include <tchar.h> #include <Windows.h> # ...

  3. 攻防世界 reverse 进阶 8-The_Maya_Society Hack.lu-2017

    8.The_Maya_Society Hack.lu-2017 在linux下将时间调整为2012-12-21,运行即可得到flag. 下面进行分析 1 signed __int64 __fastca ...

  4. 热更新基础--AssetBundle学习笔记

    一.简介 AssetBundle简称AB包,特定平台的资产压缩包(包括模型.贴图.预设体.音效.材质球等资产). 作用:Resources下的资源只读且打包后不可修改,而AB包存储位置自定,后期可以动 ...

  5. HTTPS证书通过cert-manager自动获取,部署,续期

    HTTP-01验证和DNS-01验证 使用cert-manager给阿里云的DNS域名授权SSL证书 第一步:安装cert-manager 配置 CRD kubectl apply -f https: ...

  6. 经典变长指令ModR/M

    变长指令 不是所有的指令都是,看到opcode就知道有多长(定长指令),当指令中出现内存操作对象的时候,就需要在操作码后面附加一个字节来进行补充说明,这个字节被称为ModR/M. 该字节的8个位被分成 ...

  7. 9. resultMap 结果映射集

    @Data public class CreditCard extends BankCard { /** * 消费额度 */ private String creditLine; } @Data pu ...

  8. Flutter 状态管理- 使用 MobX

    文 / Paul Halliday, developer.school 创始人 众所周知,状态管理是每个软件项目都需要持续迭代更新的方向.它并不是一个「一次性」的工作, 而需要不断确保你遵循的最佳实践 ...

  9. Day16_92_Java IO 基础概念

    Java IO 基础概念 流根据方向分为 输入流 和 输出流. 注意 : 输入和输出是相对与内存而言的,从内存出来就是输出,到内存中去就是输入. 输入叫做 "读" , 输出叫做 & ...

  10. Day07_39_集合中的remove()方法 与 迭代器中的remove()方法

    集合中的remove()方法 与 迭代器中的remove()方法 深入remove()方法 iterator 中的remove()方法 collection 中的remove(Object)方法 注意 ...