与掘金文章同步,地址: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. P1036_选数(JAVA语言)

    题目描述 已知 n 个整数x1​,x2​,-,xn​,以及1个整数k(k<n).从n个整数中任选k个整数相加,可分别得到一系列的和.例如当n=4,k=3,4个整数分别为3,7,12,19时,可得 ...

  2. Elasticsearch 分页查询

    目录 前言 from + size search after scroll api 总结 参考资料 前言 我们在实际工作中,有很多分页的需求,商品分页.订单分页等,在MySQL中我们可以使用limit ...

  3. JAVA线上故障排查手册-(推荐)

    参考:https://fredal.xin/java-error-check?hmsr=toutiao.io&utm_medium=toutiao.io&utm_source=tout ...

  4. PaddleOCR详解

    @ 目录 PaddleOCR简介 环境配置 PaddleOCR2.0的配置环境 Docker 数据集 文本检测 使用自己的数据集 文本识别 使用自己的数据集 字典 自定义字典 添加空格类别 文本角度分 ...

  5. [BFS]最小转弯问题

    最小转弯问题 Description 给出一张地图,这张地图被分为 n×m(n,m<=100)个方块,任何一个方块不是平地就是高山.平地可以通过,高山则不能.现在你处在地图的(x1,y1)这块平 ...

  6. GAMES101作业2

    作业任务: 填写并调用函数 rasterize_triangle(const Triangle& t). 即实现光栅化 该函数的内部工作流程如下: 创建三角形的 2 维 bounding bo ...

  7. BUAA_OS lab3 难点梳理

    BUAA_OS lab3 难点梳理 实验难点 进程创建 对于初始化部分,首先需要在pmap.c中修改mips_vm_init()函数,为envs开空间,并map到UENVS空间. 其次,模仿page_ ...

  8. MySQL性能压力基准测试工具sysbench

    1.sysbench介绍 这里介绍一款MySQL数据库的压力测试软件sysbench,用它来进行基准测试. sysbench 是一个开源的.模块化的.跨平台的多线程性能测试工具, 可以用来进行CPU. ...

  9. Scrapy入门到放弃01:开启爬虫2.0时代

    前言 Scrapy is coming!! 在写了七篇爬虫基础文章之后,终于写到心心念念的Scrapy了.Scrapy开启了爬虫2.0的时代,让爬虫以一种崭新的形式呈现在开发者面前. 在18年实习的时 ...

  10. JavaCV 视频滤镜(LOGO、滚动字幕、画中画、NxN宫格)

    其实,在JavaCV中除了FFmpegFrameGrabber和FFmpegFrameRecorder之外,还有一个重要的类,那就是FFmpegFrameFilter. FFmpegFrameFilt ...