详解ES6中的代理模式——Proxy


Posted in Javascript onJanuary 08, 2018

什么是代理模式

代理模式(英语:Proxy Pattern)是程序设计中的一种设计模式。

所谓的代理者是指一个类别可以作为其它东西的接口。代理者可以作任何东西的接口:网络连接、内存中的大对象、文件或其它昂贵或无法复制的资源。

著名的代理模式例子为引用计数(英语:reference counting)指针对象。

当一个复杂对象的多份副本须存在时,代理模式可以结合享元模式以减少内存用量。典型作法是创建一个复杂对象及多个代理者,每个代理者会引用到原本的复杂对象。而作用在代理者的运算会转送到原本对象。一旦所有的代理者都不存在时,复杂对象会被移除。

上面是维基百科中对代理模式的一个整体的定义.而在JavaScript中代理模式的具体表现形式就是ES6中的新增对象---Proxy

什么是Proxy对象

在MDN上对于 Proxy 的解释是:

Proxy 对象用于定义基本操作的自定义行为(如属性查找,赋值,枚举,函数调用等)。

简单来说: Proxy 对象就是可以让你去对JavaScript中的一切合法对象的基本操作进行自定义.然后用你自定义的操作去覆盖其对象的基本操作.也就是当一个对象去执行一个基本操作时,其执行的过程和结果是你自定义的,而不是对象的.

:sweat:好吧,用文字表达可能太复杂了.我们还是直接上代码吧.

首先Proxy的语法是:

let p = new Proxy(target, handler);

其中:

  1. target 是你要代理的对象.它可以是JavaScript中的任何合法对象.如: (数组, 对象, 函数等等)
  2. handler 是你要自定义操作方法的一个集合.
  3. p 是一个被代理后的新对象,它拥有 target 的一切属性和方法.只不过其行为和结果是在 handler 中自定义的.

然后让我们来看这段代码:

let obj = {
 a: 1,
 b: 2,
}

const p = new Proxy(obj, {
 get(target, key, value) {
  if (key === 'c') {
   return '我是自定义的一个结果';
  } else {
   return target[key];
  }
 },

 set(target, key, value) {
  if (value === 4) {
   target[key] = '我是自定义的一个结果';
  } else {
   target[key] = value;
  }
 }
})
console.log(obj.a) // 1
console.log(obj.c) // undefined
console.log(p.a) // 1
console.log(p.c) // 我是自定义的一个结果
obj.name = '李白';
console.log(obj.name); // 李白
obj.age = 4;
console.log(obj.age); // 4
p.name = '李白';
console.log(p.name); // 李白
p.age = 4;
console.log(p.age); // 我是自定义的一个结果

从上面这段代码中,我可以很清楚的看到 Proxy 对象的作用.即是之前所受的 用于定义基本操作的自定义行为 .同样的 get 和 set 操作.没有没代理的对象所得的结果是其JavaScript本身的执行机制运行计算后所得到的.而被代理了的对象的结果则是我们自定义的.

Proxy所能代理的范围--handler

在上面代码中,我们看到了构造一个代理对象时所传的第二个参数 handler ,这个 handler 对象是由 get 和 set 两个函数方法组成的.这两个方法会在一个对象被 get 和 set 时被调用执行,以代替原生对象上的操作.那么为什么在 handler ,定义 get 和 set 这两个函数名之后就代理对象上的 get 和 set 操作了呢?

实际上 handler 本身就是ES6所新设计的一个对象.它的作用就是用来 自定义代理对象的各种可代理操作 。它本身一共有13中方法,每种方法都可以代理一种操作.其13种方法如下:

handler.getPrototypeOf()

// 在读取代理对象的原型时触发该操作,比如在执行 Object.getPrototypeOf(proxy) 时。

handler.setPrototypeOf()

// 在设置代理对象的原型时触发该操作,比如在执行 Object.setPrototypeOf(proxy, null) 时。

handler.isExtensible()

// 在判断一个代理对象是否是可扩展时触发该操作,比如在执行 Object.isExtensible(proxy) 时。

handler.preventExtensions()

// 在让一个代理对象不可扩展时触发该操作,比如在执行 Object.preventExtensions(proxy) 时。

handler.getOwnPropertyDescriptor()

// 在获取代理对象某个属性的属性描述时触发该操作,比如在执行 Object.getOwnPropertyDescriptor(proxy, "foo") 时。

handler.defineProperty()

// 在定义代理对象某个属性时的属性描述时触发该操作,比如在执行 Object.defineProperty(proxy, "foo", {}) 时。

handler.has()

// 在判断代理对象是否拥有某个属性时触发该操作,比如在执行 "foo" in proxy 时。

handler.get()

// 在读取代理对象的某个属性时触发该操作,比如在执行 proxy.foo 时。

handler.set()

// 在给代理对象的某个属性赋值时触发该操作,比如在执行 proxy.foo = 1 时。

handler.deleteProperty()

// 在删除代理对象的某个属性时触发该操作,比如在执行 delete proxy.foo 时。

handler.ownKeys()

// 在获取代理对象的所有属性键时触发该操作,比如在执行 Object.getOwnPropertyNames(proxy) 时。

handler.apply()

// 在调用一个目标对象为函数的代理对象时触发该操作,比如在执行 proxy() 时。

handler.construct()

// 在给一个目标对象为构造函数的代理对象构造实例时触发该操作,比如在执行new proxy() 时。

Proxy的作用

对于代理模式 Proxy 的作用主要体现在三个方面:

1、 拦截和监视外部对对象的访问

2、 降低函数或类的复杂度

2、 在复杂操作前对操作进行校验或对所需资源进行管理

而对于这三个使用方面的具体表现大家可以参考这篇文章-- 实例解析ES6 Proxy使用场景

Proxy的兼容性

详解ES6中的代理模式——Proxy

参考资料:

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持三水点靠木。

Javascript 相关文章推荐
精通Javascript系列之数据类型 字符串
Jun 08 Javascript
jQuery移动和复制dom节点实用DOM操作案例
Dec 17 Javascript
JS实现QQ图片一闪一闪的效果小例子
Jul 31 Javascript
js读取配置文件自写
Feb 11 Javascript
浅谈Javascript中匀速运动的停止条件
Dec 19 Javascript
jQuery图片轮播实现并封装(一)
Dec 03 Javascript
用director.js实现前端路由使用实例
Jan 27 Javascript
详解angular 中的自定义指令之详解API
Jun 20 Javascript
JS实现json对象数组按对象属性排序操作示例
May 18 Javascript
React路由鉴权的实现方法
Sep 05 Javascript
关于layui 弹出层一闪而过就消失的解决方法
Sep 09 Javascript
JavaScript如何实现监听键盘输入和鼠标监点击
Jul 20 Javascript
Vue v2.4中新增的$attrs及$listeners属性使用教程
Jan 08 #Javascript
实例解析ES6 Proxy使用场景介绍
Jan 08 #Javascript
详解weex默认webpack.config.js改造
Jan 08 #Javascript
关于vue单文件中引用路径的处理方法
Jan 08 #Javascript
浅谈React Native Flexbox布局(小结)
Jan 08 #Javascript
Node.js使用Koa搭建 基础项目
Jan 08 #Javascript
JavaScript体验异步更好的解决办法
Jan 08 #Javascript
You might like
php网站地图生成类示例
2014/01/13 PHP
PHP curl 或 file_get_contents 获取需要授权页面的方法
2017/05/05 PHP
thinkphp5框架路由原理与用法详解
2020/02/11 PHP
jQuery Autocomplete自动完成插件
2010/07/17 Javascript
两种常用的javascript数组去重方法思路及代码
2013/03/26 Javascript
jQuery队列操作方法实例
2014/06/11 Javascript
JQuery EasyUI 加载两次url的原因分析及解决方案
2014/08/18 Javascript
jQuery内容过滤选择器用法示例
2016/09/09 Javascript
Vue.2.0.5实现Class 与 Style 绑定的实例
2017/06/20 Javascript
js构建二叉树进行数值数组的去重与优化详解
2018/03/26 Javascript
Angular 5.x 学习笔记之Router(路由)应用
2018/04/08 Javascript
利用JavaScript的Map提升性能的方法详解
2019/08/14 Javascript
[58:57]2018DOTA2亚洲邀请赛3月29日小组赛B组 Effect VS VGJ.T
2018/03/30 DOTA
[01:00:17]DOTA2-DPC中国联赛 正赛 SAG vs Dynasty BO3 第二场 1月25日
2021/03/11 DOTA
python编程通过蒙特卡洛法计算定积分详解
2017/12/13 Python
python 集合 并集、交集 Series list set 转换的实例
2018/05/29 Python
Python实现的生产者、消费者问题完整实例
2018/05/30 Python
python实现定时提取实时日志程序
2018/06/22 Python
详解python中的Turtle函数库
2018/11/19 Python
在django中图片上传的格式校验及大小方法
2019/07/28 Python
决策树剪枝算法的python实现方法详解
2019/09/18 Python
python开发实例之python使用Websocket库开发简单聊天工具实例详解(python+Websocket+JS)
2020/03/18 Python
jupyter notebook 多行输出实例
2020/04/09 Python
Tensorflow tf.nn.atrous_conv2d如何实现空洞卷积的
2020/04/20 Python
django 获取字段最大值,最新的记录操作
2020/08/09 Python
HTML5 的新的表单元素(datalist/keygen/output)使用介绍
2013/07/19 HTML / CSS
实习生体会的自我评价范文
2013/11/28 职场文书
小学生检讨书大全
2014/02/06 职场文书
农村党建工作汇报材料
2014/10/27 职场文书
2014年个人师德工作总结
2014/12/04 职场文书
专家推荐信怎么写
2015/03/25 职场文书
2016年大学迎新工作总结
2015/10/14 职场文书
《圆的面积》教学反思
2016/02/19 职场文书
2017春节晚会开幕词
2016/03/03 职场文书
pytorch中[..., 0]的用法说明
2021/05/20 Python
MySQL 执行数据库更新update操作的时候数据库卡死了
2022/05/02 MySQL