与掘金文章同步,地址: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. 在SSM框架中如何将图片上传到数据库中

    今天我们来看看SSM中如何将图片转换成二进制,最后传入到自己的数据库中,好了,废话不多说,我们开始今天的学习,我这里用的编辑器是IDEA 1.导入图片上传需要的jar依赖包 1 <depende ...

  2. 干掉前端!3分钟纯 Java 注解搭个管理系统

    大家好,我是小富~ 最近接触到个新项目,发现它用了一个比较有意思的框架,可以说实现了我刚入行时候的梦想,所以这里马不停蹄的和大家分享下. 在我刚开始工作接触的项目都还没做前后端分离,经常需要后端来维护 ...

  3. 【MCU】国民N32固件库移植

    目录 前言 移植N32Gxxx系列要点 前言 链接: 李柱明博客 移植AT32库&FreeRTOS教程 由于大部分国产MCU移植固件库.RTOS源码都是差不多的,所以本文不讲细节,如想熟悉移植 ...

  4. 【工程应用一】 多目标多角度的快速模板匹配算法(基于NCC,效果无限接近Halcon中........)

    愿意写代码的人一般都不太愿意去写文章,因为代码方面的艺术和文字中的美学往往很难兼得,两者都兼得的人通常都已经被西方极乐世界所收罗,我也是只喜欢写代码,让那些字母组成美妙的歌曲,然后自我沉浸在其中自得其 ...

  5. 没想到吧,Java开发 API接口可以不用写 Controller了

    本文案例收录在 https://github.com/chengxy-nds/Springboot-Notebook 大家好,我是小富~ 今天介绍我正在用的一款高效敏捷开发工具magic-api,顺便 ...

  6. [.net] 关于Exception的几点思考和在项目中的使用(三)

    本文链接: https://www.cnblogs.com/hubaijia/p/about-exceptions-3.html 系列文章: 关于Exception的几点思考和在项目中的使用(一) 关 ...

  7. Dynamics CRM邮箱配置

    Dynamics CRM对邮箱有很好的支持,开通邮箱后方便用户通过邮件进行Dynamics CRM的业务处理,同时也可以作为一直消息流提醒的手段应用于审批.通知等场景,可以做一些更深入的功能拓展. 本 ...

  8. 「Unity卡牌自走棋」项目NABCD分析

    项目 内容 这个作业属于哪个课程 2021学年春季软件工程(罗杰 任健) 这个作业的要求在哪里 团队项目-初次邂逅,需求分析 在这个课程的目标是 锻炼在大规模开发中的团队协作能力 这个作业在哪个具体方 ...

  9. Ubuntu安装docker/docker-compose(在全新系统状态下的安装)

    设置仓库 更新 apt 包索引. $ sudo apt-get update 安装 apt 依赖包,用于通过HTTPS来获取仓库: $ sudo apt-get install \ apt-trans ...

  10. 干掉 Feign,Spring Cloud Square 组件发布

    Spring Cloud Square 是什么 谈起 Spring Cloud 生态大家一定对 Feign 不陌生,如下图所示,Feign 可以把底层(okhttp.httpclient)Rest 的 ...