ES给开发者提供了一个新特性:Proxy,就是代理的意思。也就是我们这一节要介绍的知识点。

以前,ATM还没有那么流行的时候(暴露年纪),我们去银行存款或者取款的时候,需要在柜台前排队,等柜台工作人员帮我们办理业务,这也是一种代理,我们自己无法修改我们银行账户上的数据,需要代理给柜员,帮我们办理存钱或者取现业务,而Proxy也是这样的一种机制。

Proxy的实现

我们先来看看Proxy的实现:

    //定义一个对象person
var person = {"name":"张三"}; //创建一个代理对象pro,代理person的读写操作
var pro = new Proxy(person,{
get:function(target,property){
return "李四"
}
}); pro.name;//李四

先定义一个对象,含有name属性,值为“张三”,创建一个代理对象pro,对象person的操作都交给代理对象pro,这不,看最后一句代码,如果你要读取person对象的name属性,就要用pro.name,而不是person的name。我们看到的结果是:“李四“而不是person对象重点张三,因为代理过程中,get方法实现了拦截的作用,不管你读取什么属性,我都返回”李四“。

这就是代理Proxy的作用,将一个对象交给了Proxy代理,然后通过编写处理函数,来拦截目标对象的操作。上面的案例,你可以理解为,person对象的name属性值不想被别人知道是“张三“,就设置了一个代理,让别人读取的时候,只获取到”李四“。

set方法

而上面提到的“编写处理函数“,get方法就是其中一个,除了get方法以外,还有一个很常用的是:set方法,它用于拦截对对象的写操作。

我们来结合银行的例子,来用get方法和set方法的实现,这段代码有点长,但是注释很详细,注意看代码注释:

 //定义一个对象,含有RMB和dollar属性值
var bankAccount = {"RMB":1000,"dollar":0};
//创建一个Proxy代理实例
var banker = new Proxy(bankAccount,{
//编写get处理程序
get:function(target, property){
//判断余额是否大于0
if(target[property] > 0){
//有余额,就返回余额值
return target[property];
}else{
//没钱了
return "余额不足";
}
},
//编写set处理程序
set:function(target,property,value){
//存入的数额必须是一个数字类型
if(!Number.isInteger(value)){
return "请设置正确的数值";
}
//修改属性的值
target[property] = value;
}
}); banker.RMB;
//结果:1000
banker.dollar;
//结果:余额不足 //修改dollar属性的值,值是字符串类型
banker.dollar = "五百";
banker.dollar;
//结果:余额不足 //修改dollar属性的值,值是数字类型
banker.dollar = 500;
banker.dollar;
//结果:500

几乎每一句代码都有注释,这段代码对应的故事情节是这样的:老王有的银行账户里面有一些存款,其中人民币1000元,美元0元。

 var bankAccount = {"RMB":1000,"dollar":0};

有一天,他来到银行柜台前,找到一个叫banker的工作人员,取款之前看看账户里面还有多少钱,然后工作人员banker开始帮他操作(也就是代理)。

    banker.RMB;
//结果:1000
banker.dollar;
//结果:余额不足

banker告诉他:“您账户里面有人民币1000元,可以取款的,但美元余额不足“。

接着,老王不打算取款了,打算存500美元。.

在填写存款单据的时候,把500不小心写成了“五百“,banker告诫老王:”这样是写不行的,一定要写阿拉伯数字,这样写银行无法帮您存款的“。结果存款失败,账户里面的美元还是0元。

    banker.dollar = "五百";
banker.dollar;
//结果:余额不足

没关系,马上改过来,把“五百“改成500。

    banker.dollar = 500;
banker.dollar;
//结果:500

存款成功,账户里面的美元已有500元。

故事的整个经过就是这样,有了Proxy代理(银行工作人员bank),帮助老王完成查看银行存款和取款的操作(代理),避免了一些误操作。

get方法拦截了读取操作,set方法拦截了改写操作。Proxy除了支持以上拦截程序,还支持一系列的拦截函数,我们选择几个常用的讲解!

ownKeys( )方法

ownKeys拦截操作,拦截过滤Object.ownKeys()对对象的属性遍历。

 //定义一个对象person,有三个属性
let person = {"name":"老王","age":40,"height":1.8}; //创建一个代理对象
let proxy = new Proxy(person,{
//ownKeys过滤对对象的属性遍历
ownKeys:function(target){
return ["name","age"]
}
}); Object.keys(person);
//结果:["name", "age","height"] Object.keys(proxy);
//结果:["name", "age"]

我们编写的ownKeys方法程序,不管你有多少属性,只返回两个属性name和age。我们看最后两行代码:Object.keys(person); 这里我们不使用代理,直接用keys( )函数遍历person对象,得到的person对象的原本属性"name"、 "age"和"height"。而Object.keys(proxy) 这句代码遍历的是被代理的proxy对象,所以,得到的只是被过滤后的结果:[“name”,”age”]。

has( )方法

has( )拦截操作:拦截key in object的操作,结果会返回一个布尔值。

    var person = {
"name":"张三",
"age":20
}; var proxy = new Proxy(person, {
has: function(target, prop) {
if(target[prop] === undefined){
return false;
}else{
return true;
}
}
}); "name" in proxy;//结果:true
"height" in proxy;//结果:false

has( )方法用于是判断是否含有指定的键值对,有,就返回true。否则返回false。

对象含有name属性,所以返回true,没有height属性,返回false。

apply( )方法

除了对象类型的变量可以被代理,函数也可以被代理。如果被代理的变量是一个函数,那么还会支持一个拦截程序:apply调用。

    //创建一个函数fn
let fn = function(){
alert('我是前端君');
};
//创建一个代理实例,代理函数fn
let proxy = new Proxy(fn,{
apply:function(){
alert('我是隔壁老王');
}
}); proxy();//结果:我是隔壁老王

最后一句代码,proxy本身是一个代理实例对象,因为它代理的是一个函数fn,所以可以直接用函数的形式调用proxy( );当它当作函数调用的时候,就会被apply拦截,执行alert('我是隔壁老王')。

Proxy.revocable( )取消代理

如果创建了代理之后又想取消代理的话,我们可以用Proxy.revocable( )函数来实现,它会返回一个对象,对象中含有一个proxy属性,它就是Proxy的代理实例对象;还有一个revoke属性,它是一个方法,用于取消代理。

我们用实例演示一下:

    //定义一个对象
let person = {"name":"张三"};
//定义一个代理处理程序
let handle = {
get:function(target,prop){
return "李四";
}
}; //使用Proxy.revocable()进行代理
let object = Proxy.revocable(person,handle); object.proxy.name;//结果:李四 //调用返回对象object的revoke方法,取消代理
object.revoke(); object.proxy.name;//报错,代理被取消

这个案例大家要注意的是Proxy.revocable( )方法返回的结果,它是一个对象,在控制台打印出来后的结果是:Object{ proxy:Object , revoke:function(){....} }。有一个proxy属性,它就是Proxy代理实例,还有一个属性revoke,它是一个方法,专用于取消代理。

我们使用object.proxy.name来读取name的属性,由于被代理拦截了,只能读取到“李四”,接着我们调用revoke( )方法取消代理,然后再使用object.proxy.name的时候就会报错了,代理已经不存在了。

以上就是Proxy代理的介绍,关于其他的拦截操作就不一一介绍,包括:

  • defineProperty( )

  • deleteProperty( )

  • enumerate( )

  • getOwnPropertyDescriptor( )

  • getPrototypeOf( )

  • isExtensible( )

  • preventExtensions( )

  • setPrototypeOf( )

本节小结

总结:ES6带了的Proxy代理机制,它提供了一些拦截操作:set、get、apply、has、ownKeys等,我们可以根据特定的需求编写拦截程序,达到我们想要的效果;此外,我们也可以利用Proxy.revocable( )实现取消代理。
更多前端学习内容文章干货请关注我的专栏(不断更新)

阿里名厂标准web前端高级工程师教程目录大全,从基础到进阶,看完保证您的薪资上升一个台阶

在这里我给大家准备了很多的学习资料

其实你与阿里工程师的差距只差这些东西

新的知识点来了-ES6 Proxy代理 和 去银行存款有什么关系?的更多相关文章

  1. es6 proxy代理

    es6 新增构造函数 Proxy Proxy 构造函数,可以使用new 去创建,可以往里面插入两个参数,都是对象 let target = {} let handler = {} let proxy ...

  2. ES6 proxy代理详解及用法

    proxy官方的详细解释为代理器,个人理解为相当于一个拦截器,外部的所有访问必须先通过这层拦截,监视到对象的读写过程,因此提供了这 种机制对外部的访问进行过滤和修改. 上述例子为proxy new一个 ...

  3. ES6 proxy(代理拦截) &&Reflect

  4. ES6新特性:Proxy代理器

    ES6新特性:Proxy: 要使用的话, 直接在浏览器中执行即可, node和babel目前还没有Proxy的polyfill;,要使用的话,直接在浏览器中运行就好了, 浏览器的兼容性为:chrome ...

  5. 详解es6中Proxy代理对象的作用

    在es6中新添加了Proxy,那么它有什么作用啊?Proxy本意为代理,而es6中的Proxy也就是代理对象,那么代理对象感觉听起来很模糊,在这里就解释一下Proxy代理对象的作用. Proxy的主要 ...

  6. Vue3.0 响应式数据原理:ES6 Proxy

    Vue3.0 开始用 Proxy 代替 Object.defineProperty了,这篇文章结合实例教你如何使用Proxy 本篇文章同时收录[前端知识点]中,链接直达 阅读本文您将收获 JavaSc ...

  7. es6 Proxy对象详解

    Proxy用于修改某些操作的默认行为,也可以理解为在目标对象之前架设一层拦截,外部所有的访问都必须先通过这层拦截,因此提供了一种机制,可以对外部的访问进行过滤和修改.这个词的原理为代理,在这里可以表示 ...

  8. php设计模式之Proxy(代理模式)和Facade(外观)设计模式

    Proxy(代理模式)和Facade(外观)设计模式它们均为更复杂的功能提供抽象化的概念,但这两种实现抽象化的过程大不相同 Proxy案例中,所有的方法和成员变量都来自于目标对象,必要时,该代理能够对 ...

  9. Proxy 代理模式

    简介 代理模式是用一个简单的对象来代替一个复杂的或者创建耗时的对象. java.lang.reflect.Proxy RMI 代理模式是对象的结构模式.代理模式给某一个对象提供一个代理对象,并由代理对 ...

随机推荐

  1. iOS 构建静态库

    一..a 文件静态库打包 打开 Xcode 创建一个新的 Static Library 工程,取名 MyStaticLibrary. 创建工程完毕后,系统自动创建了一个同名类,添加一个方法用于测试. ...

  2. Spinner的简单实用

    1.Spinner的功能 Spinner在Android中主要实现的是一个下拉列表,这个下拉列表相当于弹出一个弹出一个菜单供用户选择.即Spinner提供一个快速的方法从一组中选择一个值,默认状态下S ...

  3. CodeForces 687A NP-Hard Problem

    Portal:http://codeforces.com/problemset/problem/687/A 二分图染色 好模板题 有SPJ 值得注意的是,因为C++的奇妙的运算机制 若在vector变 ...

  4. 实验四 数据查询3-group by等

    实验四 数据库查询 一.  实验内容: 1. Group by语句 2. Having 语句 3. Order by语句 4. Limit语句 5. Union语句 6. Handler语句 二.  ...

  5. P1130 红牌(动态规划)

    P1130 红牌 思路如下 这一题很像数字金字塔,我们可以正着求最小时间,当然也可以逆着求最小时间, 如果正着求:那么我们怎么求状态转移方程呢?,在这里我们假定状态转移方程为:dp[ i ][ j ] ...

  6. 高性能/并发的保证-Netty在Redisson的应用

    前言 ​ Redisson Github: https://github.com/redisson/redisson ​ Redisson 官网:https://redisson.pro/ Redis ...

  7. 关于C#三层架构增删改查中的“查询”问题

    序:问题总是反复出现,可能只是一个小小的问题,但是就像肉中刺. 问题: 关于“姓名”字段的拼接问题 姓名字段的拼接:this.Repeater1.DataSource = db.GetList(&qu ...

  8. 《Three.js 入门指南》2.3.1- 照相机 - 正交投影demo

    <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8&quo ...

  9. JVM类加载过程详细分析

    双亲委派加载模型 为什么需要双亲委派加载模型 主要是为了安全,避免用户恶意加载破坏JVM正常运行的字节码文件,比如说加载一个自己写的java.util.HashMap.class.这样就有可能造成包冲 ...

  10. JAVA中使用使Math 类操作数据

    转自:https://www.imooc.com/code/2342 侵删! Math 类位于 java.lang 包中,包含用于执行基本数学运算的方法, Math 类的所有方法都是静态方法,所以使用 ...