Proxy 与 Reflect 是 ES6 为了操作对象引入的 API 。
1、Proxy
Proxy 可以对目标对象的读取、函数调用等操作进行拦截,然后进行操作处理。它不直接操作对象,而是像代理模式,通过对象的代理对象进行操作,在进行这些操作时,可以添加一些需要的额外操作。
Proxy基本用法:
Proxy 用于修改某些操作的默认行为,等同于在语言层面做出修改,所以属于一种“元编程”(meta programming),即对编程语言进行编程。
Proxy 可以理解成,在目标对象之前架设一层“拦截”,外界对该对象的访问,都必须先通过这层拦截,因此提供了一种机制,可以对外界的访问进行过滤和改写。
Proxy 这个词的原意是代理,用在这里表示由它来“代理”某些操作,可以译为“代理器”
let pro = new Proxy(target,handler);
其中 new Proxy相当于创建了一个Proxy实例,target为所要拦截的目标对象,handler也是一个对象,里面定义的是对拦截对象所要进行的拦截方法
<script type="text/javascript"> //Proxy let target = {name:'rdb',pwd:123456} let handler = { get:function(target,propKey){ return target[propKey]; } } let pro = new Proxy(target,handler); console.log(pro.name,pro.pwd); //rdb 123456 </script>
Proxy常用的拦截方法
(1)get(target, propKey, receiver):拦截对象属性的读取,第一个参数为目标对象,第二个参数为属性名称,第三个属性为操作所针对的对象(可选参数)。
<script type="text/javascript"> //Proxy let target = {name:'rdb',pwd:123456} let handler = { get:function(target, propKey, receiver){ if(propKey in target){ console.log("success"); }else{ console.log("false"); } return Reflect.get(target, propKey, receiver); } } let pro = new Proxy(target,handler); console.log(pro.name,pro.pwd); //rdb 123456 </script>
(2)set(target, propKey, value, receiver):拦截对象属性的设置,第一个参数为目标对象,第二个参数为属性名,第三个参数为属性值,第四个参数为操作行为所针对的对象(可选参数)。
<script type="text/javascript"> //Proxy let target = {name:'rdb',pwd:123456} let handler = { get:function(target, propKey, receiver){ if(propKey in target){ console.log("success"); }else{ console.log("false"); } return Reflect.get(target, propKey, receiver); }, set:function (target, propKey, value, receiver) { if(propKey=='pwd'){ if(!Number.isInteger(value)){ throw new TypeError('The age is not an integer'); }else{ console.log("set success"); } }else{ console.log("set success"); } return Reflect.set(target, propKey, value, receiver); } } let pro = new Proxy(target,handler); console.log(pro.name,pro.pwd); //rdb 123456 pro.name='jack'; pro.pwd=123; console.log(pro.name,pro.pwd); //jack 123 //当pwd是字符串是会抛出异常 </script>
(3)has(target, propKey):用来拦截对象是否具有某个属性值的操作,第一个参数为目标对象,第二个参数为属性名
<script type="text/javascript"> //Proxy let target = {name:'rdb',pwd:123456} let handler = { get:function(target, propKey, receiver){ if(propKey in target){ console.log("success"); }else{ console.log("false"); } return Reflect.get(target, propKey, receiver); }, set:function (target, propKey, value, receiver) { if(propKey=='pwd'){ if(!Number.isInteger(value)){ throw new TypeError('The age is not an integer'); }else{ console.log("set success"); } }else{ console.log("set success"); } return Reflect.set(target, propKey, value, receiver); }, has:function(target, propKey){ console.log('handle has'); return propKey in target; } } let pro = new Proxy(target,handler); console.log(pro.name,pro.pwd); //rdb 123456 pro.name='jack'; pro.pwd=123; console.log(pro.name,pro.pwd); //jack 123 //当pwd是字符串是会抛出异常 console.log('name' in pro);//判断 console.log('pwd' in pro);//判断 </script>
2、Reflect
Reflect 可以用于获取目标对象的行为,它与 Object 类似,但是更易读,为操作对象提供了一种更优雅的方式。它的方法与 Proxy 是对应的