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>