与掘金文章同步,地址: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并发框架AQS系列(三):独占锁(Exclusive Lock)

    一.前言 优秀的源码就在那里 经过了前面两章的铺垫,终于要切入正题了,本章也是整个AQS的核心之一 从本章开始,我们要精读AQS源码,在欣赏它的同时也要学会质疑它.当然本文不会带着大家逐行过源码(会有 ...

  2. 14、运行Django时浏览器中遇到Refused to display 'url' in a frame because it set 'X-Frame-Options' to 'deny'

    问题:Refused to display 'url' in a frame because it set 'X-Frame-Options' to 'deny' 解决办法: 只需要在 Djagno ...

  3. [源码解析] 并行分布式框架 Celery 之 worker 启动 (2)

    [源码解析] 并行分布式框架 Celery 之 worker 启动 (2) 目录 [源码解析] 并行分布式框架 Celery 之 worker 启动 (2) 0x00 摘要 0x01 前文回顾 0x2 ...

  4. 数据库MySQL一

    P252 1.MySQL 最为主要使用的数据库 my sequel 不容易查找数据 DB数据库 存储数据的仓库,它保存了一系列有组织的数据 DBMS数据库管理系统,数据库是通过DBMS创建和操作的容器 ...

  5. 【笔记】《Redis设计与实现》chapter19 事务

    chapter19 事务 Redis通过MULTI.EXEC.WATCH等命令来实现事务功能 19.1 事务的实现 事务开始 redis> MULTI ok 通过切换客户端状态的flag属性的R ...

  6. 在Visual Studio 中使用git——给Visual Studio安装 git插件(二)

    在Visual Studio 中使用git--什么是Git(一) 第二部分: 给Visual Studio安装 git插件 如果要使用 git 进行版本管理,其实使用 git 命令行工具就完全足够了, ...

  7. Flutter 状态管理- 使用 MobX

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

  8. JavaScript遍历对象方法总结

    前言 本篇内容将按照下图展开: 遍历Object Object最常见的遍历方法方法就是使用for...in...,但其有一定的局限性,比如只能遍历可枚举属性.虽然Object无法直接使用for循环和f ...

  9. Word 查找和替换字符串方法

    因为项目需要通过word模板替换字符串 ,来让用户下载word, 就在网上找了找word查找替换字符串的库或方法,基本上不是收费,就是无实现,或者方法局限性太大 .docx 是通过xml来存储文字和其 ...

  10. 被动信息搜集 - Python安全攻防

    概述: 被冻信息搜集主要通过搜索引擎或者社交等方式对目标资产信息进行提取,通常包括IP查询,Whois查询,子域名搜集等.进行被动信息搜集时不与目标产生交互,可以在不接触到目标系统的情况下挖掘目标信息 ...