js Proxy的原理详解


Posted in Javascript onMay 25, 2021

什么是代理模式

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

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

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

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

在某些情况下,一个对象不适合或者不能直接引用另一个对象,而代理对象可以在客户端和目标对象之间起到中介的作用。

代理模式就是为其他用户提供一种代理,用户不用知道买房的具体过程,而用户应该关心的是如何获得满意的结果,代理所需要做的事情就是完成这一买房的过程。

什么是Proxy

Proxy支持的拦截操作有许多中,目前只针对get(target, propKey, receiver)和set(target, propKey, value, receiver)来讲。

  • get方法:拦截对象属性的读取;
  • set方法:拦截对象属性的设置。

get(target, propKey, receiver)

定义一个Person对象,它将被Proxy代理,外界通Proxy实例对象来访问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对象已经被Proxy代理了,所以每当我通过该Proxy实例对象访问Person中存在的属性时,都会调用get方法,get方法是拦截对象属性的读取的。

get: function (target, property) 中的两个参数target和property分别接收到的信息如图所示

js Proxy的原理详解

通过该代理对象访问Person对象中存在的属性不会出现任何异常,如果访问不存在的属性会发生什么?

js Proxy的原理详解

是什么,以至于访问不存在的属性时,它会抛出异常呢?

这是因为外界对Person对象的访问都必须先通过Proxy设置的拦截层,而拦截层提供了一种机制可以对外界的访问进行过滤和改写。

// 判断外界访问的对象属性是否存在于目标对象中。
if (property in target) {
    return target[property];
} else {
    // 如果外界访问的对象属性不存在与目标对象中,抛出异常。
    throw new ReferenceError('Property "' + property + '" 不存在。');
}

if语句就是拦截层的具体操作,即对外界的访问进行过滤和改写。如果没有,访问不存在的属性就会返回undefined。

js Proxy的原理详解

set(target, propKey, value, receiver)

依旧是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的三个参数分别接收到的信息如下图所示。

js Proxy的原理详解

set方法用于拦截某个属性的赋值操作,我如果对age的赋值操作不满足条件时,会发生什么?

js Proxy的原理详解

很明显,会抛出异常。

总结

Proxy就是拦截层,你给出被拦截的对象,外界访问这个对象必须先通过拦截层,即访问Proxy的实例对象。通过Proxy为外界访问进行过滤和改写,如赋值时需满足某些条件。

代理对象中还有许多的方法,如has、deleteProperty、ownKeys、getOwnPropertyDescriptor等,都是用于拦截不同的情况而出现的。

以上就是js Proxy的原理详解的详细内容,更多关于js Proxy的资料请关注三水点靠木其它相关文章!

Javascript 相关文章推荐
javascript parseInt() 函数的进制转换注意细节
Jan 08 Javascript
javascript圆盘抽奖程序实现原理和完整代码例子
Jun 03 Javascript
JavaScript实现计算字符串中出现次数最多的字符和出现的次数
Mar 12 Javascript
使用Sticky组件实现带sticky效果的tab导航和滚动导航的方法
Mar 22 Javascript
Jquery实现select multiple左右添加和删除功能的简单实例
May 26 Javascript
JS 根据子网掩码,网关计算出所有IP地址范围示例
Apr 23 Javascript
jQuery表单对象属性过滤选择器实例详解
Sep 13 Javascript
表单元素值获取方式js及java方式的简单实例
Oct 15 Javascript
微信小程序如何获取openid及用户信息
Jan 26 Javascript
在Vue项目中使用jsencrypt.js对数据进行加密传输的方法
Apr 17 Javascript
JS根据json数组多个字段排序及json数组常用操作
Jun 06 Javascript
Vue实现仿iPhone悬浮球的示例代码
Mar 13 Javascript
解析原生JS getComputedStyle
80行代码写一个Webpack插件并发布到npm
Ajax请求超时与网络异常处理图文详解
May 23 #Javascript
vue-element-admin项目导入和导出的实现
May 21 #Vue.js
vue2实现provide inject传递响应式
May 21 #Vue.js
JS + HTML 罗盘式时钟的实现
JavaScript canvas实现流星特效
May 20 #Javascript
You might like
用PHP和ACCESS写聊天室(八)
2006/10/09 PHP
使用PHP socke 向指定页面提交数据
2008/07/23 PHP
php join函数应用
2011/05/04 PHP
php array_push()数组函数:将一个或多个单元压入数组的末尾(入栈)
2011/07/12 PHP
利用PHP实现短域名互转
2013/07/05 PHP
部署PHP项目应该注意的几点事项分享
2013/12/20 PHP
微信公众号开发之文本消息自动回复php代码
2016/08/08 PHP
Nginx下ThinkPHP5的配置方法详解
2017/08/01 PHP
用js解决数字不能换行问题
2010/08/10 Javascript
jQuery EasyUI API 中文文档 - Documentation 文档
2011/09/29 Javascript
FF(火狐)浏览器无法执行window.close()解决方案
2014/11/13 Javascript
jQuery position() 函数详解以及jQuery中position函数的应用
2015/12/14 Javascript
js判断出两个字符串最大子串的函数实现方法
2016/11/01 Javascript
JS实现求数组起始项到终止项之和的方法【基于数组扩展函数】
2017/06/13 Javascript
AngularJS实现自定义指令与控制器数据交互的方法示例
2017/06/19 Javascript
vue router仿天猫底部导航栏功能
2017/10/18 Javascript
微信小程序canvas实现刮刮乐效果
2018/07/09 Javascript
微信小程序实现录音时的麦克风动画效果实例
2019/05/18 Javascript
python使用三角迭代计算圆周率PI的方法
2015/03/20 Python
python通过字典dict判断指定键值是否存在的方法
2015/03/21 Python
解决uWSGI的编码问题详解
2017/03/24 Python
详解Python 序列化Serialize 和 反序列化Deserialize
2017/08/20 Python
Python基于回溯法子集树模板解决全排列问题示例
2017/09/07 Python
Python实现iOS自动化打包详解步骤
2018/10/03 Python
python复制列表时[:]和[::]之间有什么区别
2018/10/16 Python
Python+PyQT5的子线程更新UI界面的实例
2019/06/14 Python
基于Django统计博客文章阅读量
2019/10/29 Python
Python注释、分支结构、循环结构、伪“选择结构”用法实例分析
2020/01/09 Python
python生成xml时规定dtd实例方法
2020/09/21 Python
如何利用find命令查找文件
2015/02/07 面试题
农业大学毕业生的个人自我评价
2013/10/11 职场文书
经销商会议欢迎词
2014/01/11 职场文书
《我的伯父鲁迅先生》教学反思
2014/02/12 职场文书
敬老院义诊活动总结
2015/05/07 职场文书
python3.9之你应该知道的新特性详解
2021/04/29 Python
MySQL选择合适的备份策略和备份工具
2022/06/01 MySQL