首页 > 代码库 > ES6-Proxy and Reflect

ES6-Proxy and Reflect

依赖文件地址 :https://github.com/chanceLe/ES6-Basic-Syntax/tree/master/js

  1 <!DOCTYPE html>
  2 <html>
  3     <head>
  4         <meta charset="UTF-8">
  5         <title>[es6]-10-Proxy和Reflect</title>
  6         
  7         <script src="./js/browser.js"></script>
  8         <script type="text/babel">
  9             /*
 10              * proxy用于修改某些操作的默认行为,等同于在语言层面作出修改,属于一种元编程。
 11              * 叫做代理器。提供了一种机制,可以对外界的访问进行过滤和改写。
 12              */
 13             var obj = new Proxy({},{
 14                 get:function(target,key,receiver){
 15                     console.log(`getting ${key}`);
 16                     return Reflect.get(target,key,receiver);
 17                 },
 18                 set:function(target,key,receiver){
 19                     console.log(`setting ${key}`);
 20                     return Reflect.set(target,key,receiver);
 21                 }
 22             })
 23             //上面代码对一个空对象架设了一层拦截,重定义了属性的读取和设置行为。
 24             obj.count = 1;
 25             ++obj.count;
 26             //结果 表明,Proxy实际上重载了点运算符。
 27             
 28             /*
 29              * es6原生提供Proxy构造函数,用来生成Proxy实例。
 30              * var proxy = new Proxy(target,handler);
 31              * Proxy对象的所有用法,都是上面这种形式,不同的只是Handler参数的写法。target 是目标对象,
 32              * handler参数也是一个对象,用来定制拦截行为。
 33              */
 34             
 35             var proxy1 = new Proxy({},{
 36                 get:function(target,property){
 37                     return 35;
 38                 }
 39             })
 40             console.log(proxy1.time);  //35
 41             console.log(proxy1.name);   //35
 42             
 43             /*
 44              * 要使Proxy起作用,必须对proxy实例进行操作,如果handler没有设置任何拦截,那就等同于直接通向原对象。
 45              * 一个技巧是将Proxy对象,设置到object.proxy属性,从而可以在object对象上调用。
 46              * var object = {proxy:new Proxy(target,handler)};
 47              * 
 48              * Proxy实例也可以作为其他对象的原型对象。
 49              * 
 50              * 下面是Proxy支持的拦截操作表:
 51              * 1.get(target,propKey,receiver)
 52              *     拦截对象属性的读取,比如点或方括号运算符。最后一个参数是一个对象,可选,参见Reflect.get部分。
 53              * 2.set(target,propKey,value,receiver)
 54              *     拦截对象属性的设置,返回一个布尔值。
 55              * 3.has(target,propKey)
 56              *     拦截propKey in proxy的操作,以及对象的hasOwnproperty方法,返回一个布尔值。
 57              * 4.deleteProperty(target,propKey)
 58              *      拦截delete proxy[propKey]的操作,返回一个布尔值。
 59              * 5.ownKeys(target)
 60              *         拦截Object.getOwnPropertyNames(proxy),Object.getOwnpropertySymbols(proxy)
 61              *         Object.keys(proxy),返回一个数组。该方法返回对象所有自身的属性,而Object.keys仅返回对象可遍历属性。
 62              * 6.getOwnPropertyDescriptor(target,propKey)
 63              *         拦截Object.getOwnPropertyDescvriptor(target,propKey),返回属性的描述对象。
 64              * 7.defineProperty(target,propKey,propDesc)
 65              *      拦截Object.defineProperty(target,propKey,propDesc)和Object.defineProperty(target,
 66              *         propDescs)返回一个布尔值。
 67              * 8.preventExtensions(target)
 68              *         拦截Object.preventExtensions(proxy),返回一个布尔值。
 69              * 9.getPrototypeOf(target)
 70              *         拦截Object.getPrototypeOf(proxy),返回一个对象。
 71              * 10.isExtensible(target)
 72              *         拦截Object.isExtensible(target),返回一个布尔值。
 73              * 11.setPrototypeOf(target,proto)
 74              *         拦截Object.setPrototypeOf(target,proto),返回一个布尔值。
 75              * 12.apply(target,object,args)
 76              *         拦截Proxy实例作为函数调用的操作,比如proxy(...args),proxy.call(object,...args)
 77              *         proxy.apply(...)
 78              * 13.construct(target,args)
 79              *         拦截Proxy实例作为构造函数调用的操作,比如 new proxy(...args)。
 80              * 
 81              * 
 82              * 暂时不细琢磨。先跳过
 83              */
 84             
 85             /*
 86              * Proxy.revocable()  该方法返回一个可取消的 Proxy实例。
 87              */
 88             let target = {};
 89             let handler = {};
 90             
 91             let {proxy,revoke} = Proxy.revocable(target,handler);
 92             console.log(proxy)
 93             proxy.foo = 123;
 94             console.log(proxy.foo);  //123
 95             revoke();
 96             console.log(proxy.foo);  //报错 revoked
 97             
 98             
 99             /*
100              * Reflect
101              * Reflect对象与Proxy对象一样,也是es6为了操作对象而提供的新API。
102              * 设计目的如下:
103              * 1.将Object对象上一些明显属于语言内部的方法(比如Object.defineProperty),放到Reflect对象上,现阶段,
104              *        某些方法同时在Object和Reflect对象上部署,未来的新方法将只部署在Reflect上。
105              * 2.修改某些Object方法的返回结果,让其变得更加合理。比如,Object.defineProperty(obj,name,desc)在无法
106              *      定义属性时,会抛出错误,而Reflect.defineProperty(obj,name,desc)则会返回false。
107              * 
108              * 3.让Object操作都变成函数行为。某些Object操作是命令式的,比如name in obj 和delete obj[name],
109              *   Reflect.has(obj,name)和Reflect.deleteProperty(obj,name)让它们变成了函数行为。
110              * 
111              * 4.Reflect对象的方法与Proxy对象的方法一一对应,只要是Proxy对象的方法,就能在Reflect对象上找到对应的方法。
112              *        这就让proxy对象可以方便地调用对应的Reflect方法,完成默认行为,作为修改行为的基础。也就是说,不管Proxy怎么修改默认
113              *        行为,你总可以在Reflect对象上获取默认行为。
114              * 
115              * Reflect对象的方法共13个,大部分与Object对象的同名方法的作用是相同的,而且它与Proxy对象的方法是一一对应的。
116              * 
117              * Refect.get(target,name,receiver)
118              *   查找并返回target对象的name属性,如果没有该属性,返回undefined。
119              *   如果name属性部署了读取函数,则读取函数的this绑定receiver。
120              */
121         </script>
122     </head>
123     <body>
124     </body>
125 </html>

 

ES6-Proxy and Reflect