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

什么是代理模式

代理模式(英语: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的兼容性

参考资料:

MDN---Proxy

实例解析ES6 Proxy使用场景

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

(0)

相关推荐

  • ES6中Proxy代理用法实例浅析

    本文实例讲述了ES6中Proxy代理用法.分享给大家供大家参考,具体如下: ES6中提出了一个新的特性,就是proxy,用来拦截在一个对象上的指定操作.这个功能非常的有用.举一个例子来说: var engineer = { name: 'Joe Sixpack', salary: 50 }; var interceptor = { set: function (receiver, property, value) { console.log(property, 'is changed to',

  • ES6中Proxy与Reflect实现重载(overload)的方法

    本文实例讲述了ES6中Proxy与Reflect实现重载(overload)的方法.分享给大家供大家参考,具体如下: Proxy与Reflect实现重载(overload) 从语法角度讲JavaScript不支持重载.原因很简单,JS中函数可以传入任意类型.任意个数的参数,通通可以通过在函数内使用this.arguments获得.这样,就无法实现同名函数参数列表不同实现不同功能.当然,在实际使用过程中,可以人为去检测传入实参的个数及类型,来进行不同操作.但是,我认为这不能叫做重载. ES6带来了

  • 详细探究ES6之Proxy代理

    前言 在ES6中,Proxy构造器是一种可访问的全局对象,使用它你可以在对象与各种操作对象的行为之间收集有关请求操作的各种信息,并返回任何你想做的.ES6中的箭头函数.数组解构.rest 参数等特性一经实现就广为流传,但类似 Proxy 这样的特性却很少见到有开发者在使用,一方面在于浏览器的兼容性,另一方面也在于要想发挥这些特性的优势需要开发者深入地理解其使用场景.就我个人而言是非常喜欢 ES6 的 Proxy,因为它让我们以简洁易懂的方式控制了外部对对象的访问.在下文中,首先我会介绍 Prox

  • 实例解析ES6 Proxy使用场景介绍

    ES6 中的箭头函数.数组解构.rest 参数等特性一经实现就广为流传,但类似 Proxy 这样的特性却很少见到有开发者在使用,一方面在于浏览器的兼容性,另一方面也在于要想发挥这些特性的优势需要开发者深入地理解其使用场景.就我个人而言是非常喜欢 ES6 的 Proxy,因为它让我们以简洁易懂的方式控制了外部对对象的访问.在下文中,首先我会介绍 Proxy 的使用方式,然后列举具体实例解释 Proxy 的使用场景. Proxy,见名知意,其功能非常类似于设计模式中的代理模式,该模式常用于三个方面:

  • 浅谈es6语法 (Proxy和Reflect的对比)

    如下所示: { //原始对象 let obj={ time:'2017-03-11', name:'net', _r:123 }; //(代理商)第一个参数代理对象,第二个参数真正代理的东西 let monitor=new Proxy(obj,{ // 拦截对象属性的读取 get(target,key){ return target[key].replace('2017','2018') }, // 拦截对象设置属性 set(target,key,value){ if(key==='name')

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

    什么是代理模式 代理模式(英语:Proxy Pattern)是程序设计中的一种设计模式. 所谓的代理者是指一个类别可以作为其它东西的接口.代理者可以作任何东西的接口:网络连接.内存中的大对象.文件或其它昂贵或无法复制的资源. 著名的代理模式例子为引用计数(英语:reference counting)指针对象. 当一个复杂对象的多份副本须存在时,代理模式可以结合享元模式以减少内存用量.典型作法是创建一个复杂对象及多个代理者,每个代理者会引用到原本的复杂对象.而作用在代理者的运算会转送到原本对象.一

  • 实例详解vue中的代理proxy

    目录 问题 复习一下跨域的解决方案 原理 场景 扩展几个常用的devServer配置 扩展几个vue/cli3的配置 问题 我们本地调试一般都是 npm run serve,然后打开 本机ip:8080(localhost:8080)对吧,这时候我们要调接口调试,后端的接口的地址可能在测试环境,也可能是自己电脑的 ip,总之不是你的 lcoalhost:8080,那么你调接口就会产生跨域,那么怎么办呢?就需要proxy出场了 复习一下跨域的解决方案 jsonp cors Node中间件代理(两次

  • 详解JAVA设计模式之代理模式

    什么是设计模式(Design Pattern)? 设计模式是一套被反复使用,多数人知晓的,经过分类编目的,代码设计经验的总结. 代理模式的定义? 代理模式就是为其他对象提供一种代理,以控制对这个对象的访问. 代理对象起到中介作用,可去掉功能服务或增加额外的服务. 代理对象和目标对象的关系? 代理对象:增强后的对象 目标对象:被增强的对象 他们不是绝对的,会根据情况发生变化. 代理模式的两种实现方式? 1.静态代理:代理和被代理对象在代理之前是确定的,它们都实现相同的接口或者继承相同的抽象类. 2

  • 详解javascript中的Strict模式

    简介 在ES5中,引入了strict模式,我们可以称之为严格模式.相应的sloppy mode就可以被称为非严格模式. 严格模式并不是非严格模式的一个子集,相反的严格模式在语义上和非严格模式都发生了一定的变化,所以我们在使用过程中,一定要经过严格的测试.以保证在严格模式下程序的执行和非严格模式下的执行效果一致. 使用Strict mode strict mode会改变javascript的一些表现,我们将会在下一节中进行详细的讲解. 这里先来看一下,怎么使用strict mode. Strict

  • 详解ES6中class的实现原理

    一.在ES6以前实现类和继承 实现类的代码如下: function Person(name, age) { this.name = name; this.age = age; } Person.prototype.speakSomething = function () { console.log("I can speek chinese"); }; 实现继承的代码如下:一般使用原型链继承和call继承混合的形式 function Person(name) { this.name =

  • 详解ES6 中的迭代器和生成器

    目录 1.迭代器 2.生成器 1.迭代器 Iterator是 ES6 引入的一种新的遍历机制.两个核心 迭代器是一个统一的接口,它的作用是使各种数据结构可以被便捷的访问,它是通过一个键为Symbol.iterator的方法来实现. 迭代器是用于遍历数据结构元素的指针(如数据库中的游标). // 使用迭代 // 1.使用Symbol.iterator创建一个迭代器 const items = ['one','a','b']; const it = items[Symbol.iterator]();

  • 详解ES6 中的Object.assign()的用法实例代码

    方法:Object.assign() 作用:将sourse对象的 值 赋值给目标对象,两者都有的会覆盖,target独有会保留,sourse独有会添加 使用方法: Object.assign方法实行的是浅拷贝,而不是深拷贝.也就是说,如果源对象某个属性的值是对象,那么目标对象拷贝得到的是这个对象的引用. var object1 = { a: { b: 1 } }; ar object2 = Object.assign({}, object1); object1.a.b = 2; console.

  • 详解java中动态代理实现机制

    代理模式是常用的java设计模式,它的特征是代理类与委托类有同样的接口,代理类主要负责为委托类预处理消息.过滤消息.把消息转发给委托类,以及事后处理消息等.代理类与委托类之间通常会存在关联关系,一个代理类的对象与一个委托类的对象关联,代理类的对象本身并不真正实现服务,而是通过调用委托类的对象的相关方法,来提供特定的服务. JAVA各种动态代理实现的比较 接口 interface AddInterface{ int add(int a, int b); } interface SubInterfa

  • 详解Docker中VLAN网络模式的配置

    前言 Docker作为目前最火的轻量级容器技术,有很多令人称道的功能,如Docker的镜像管理.然而,Docker同样有着很多不完善的地方,网络 方面就是Docker比较薄弱的部分.因此,我们有必要深入了解Docker的网络知识,以满足更高的网络需求. Docker网络模式选择 目前已有不少文章介绍了Docker的网络模型,但是在实际应用中还是有不少坑和需要注意的点 在Docker应用到生产环境的时候,网络模型的选择主要有以下几种 1.原生Bridge NAT模式 2.Linux Bridge

  • 详解ES6中的let命令

    let是ES6里面新的复制命令,let赋值命令只可以在{}代码块中被调用.下面通过实例给大家讲解es6中的let命令,具体内容如下所示: 1.let命令的用法和var命令类似,但let命令声明的变量只在let所在的代码块内有效 { let a=10; var b=1; } console.log(a);//Uncaught ReferenceError: a is not defined console.log(b); 2.let命令不存"声明提前"现象,因此变量一定要先声明,后使用

随机推荐