与掘金文章同步,地址: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. 数据库SQL查询作业

    --设有三个关系 --S(S#,SNAME,AGE,SEX) --SC(S#,C#,GRADE) --C(C#,CNAME,TEACHER) --(1)检索LIU老师所授课程的课程号.课程名 sele ...

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

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

  3. windows与远程linux服务器进行文件传输

    在学习pwn时找到了http://pwnable.kr这个网站,很多题目通过ssh连接, ssh otp@pwnable.kr -p2222 (pw:guest) 连接脚本: pwn_ssh=ssh( ...

  4. Genymotion下载模拟器慢

    •问题来源 Genymotion 是个很不错的 Android 模拟器,系统更新快,启动速度快: 但是服务器在国外,Android 镜像下载起来那个速度就不敢恭维了: 当然如果你可以[科学,上网]就另 ...

  5. Prometheus 配置文件中 metric_relabel_configs 配置--转载

    Prometheus 配置文件中 metric_relabel_configs 配置 参考1:https://www.baidu.com/link?url=YfpBgnD1RoEthqXOL3Lgny ...

  6. Python面向对象练习题

    1.模拟栈操作原理 先进后出 ​1.初始化(创建一个存储数据的列表) 2.进栈使用列表保存数据 ​ 3.出栈 使用列表删除数据 ​ 4.查看栈顶元素 切片获取列表最后一位数据 ​5.判断是否为空栈 6 ...

  7. Android+Java Web+MySQL实现登录注册

    1 前言&概述 这篇文章是基于此处文章的更新,更新了一些技术栈,更加贴近实际需要,以及修复了若干的错误. 这是一个前端Android+后端Java/Kotlin通过Servelt进行后台数据库 ...

  8. Spring Boot超简单的测试类demo

    1 概述 Spring Boot结合Junit的简单测试类demo,流程是先引入依赖,接着编写测试类测试运行即可. 2 依赖 <dependency> <groupId>org ...

  9. 号外号外!DevUI Admin V1.0 发布啦!

    4月是鸟儿的月份,是木棉花的月份,是 DevUI Admin 发布的月份. 广受大家期待的 DevUI Admin 终于迎来了第一个开源 Angular 版本! DevUI Admin 是一个企业级中 ...

  10. Laravel结构生成器

    简介 Laravel 的 Schema 类提供了一种与数据库无关的方式维护表.它和 Laravel 所支持的所有数据库都能很好的工作,并且提供了统一的接口. 创建和删除表 使用 Schema::cre ...