一.什么是Proxy
Proxy是es6新增的一个属性,用于修改某些操作的默认行为,可以理解为在目标对象外层设置一层“拦截”,外界如果想要访问目标对象,都必须先通过这层拦截,所以proxy提供了一种机制可以对外界的访问进行过滤和改写,用在这里proxy表示代理器的意思。
Proxy通过使用一个代理对象来包装目标对象,并提供了一组钩子函数(也称为“陷阱”),这些钩子函数可以在代理对象上进行操作。当我们对代理对象进行操作时,本质上是在调用这些钩子函数。
二.Proxy用法
在ES6中提供了Proxy构造函数,可以用这个构造函数生成Proxy实例
var proxy = new Proxy(target,handler);
在上述示例中, new Proxy()表示生成一个Proxy实例,target表示的是所要拦截的目标对象,handler是用来定制拦截行为,也是一个对象,需要向其中提供对应的处理函数,该函数将拦截对应的操作 。
三.常用Proxy属性用法
3.1 get(target,prop,receiver)
- 作用:用于拦截某个属性的读取操作
- 参数:target:目标对象 ;prop:属性名;receiver:proxy实例本身(操作行为所针对的对象,改参数是可选的)
- 示例
var person ={name:"jack"};var proxy =new Proxy(person,{get: function(target,prop) {if(prop in target){console.log(target[prop]);}else{throw new ReferenceError("Prop name \"" + propKey + "\" does not exist.")}}})proxy.name//jackproxy.age//抛出一个错误
3.2 set(target,prop,value,receiver)
- 作用:用于拦截某个属性的赋值操作
- 参数:target:目标对象;prop:属性名;value:属性值;receiver:Proxy实例本身(该参数可选)
- 示例:
var person ={name:'john'};var proxy =new Proxy(person,{set: function(target,prop,value){if(prop==='age'){if(value>200){throw new RangeError('不符合范围')}else{target[prop]=value;}}}})proxy.age=400//报错,不继续执行proxy.age=100//100
3.3 apply(target,ctx,args)
- 作用:拦截函数的调用
- 参数:target:目标对象;ctx:目标对象的上下文对象;args:目标对象的参数数组
- 示例:
var target= function(){return '目标对象';};var handler={apply:function(){return '代理对象';}};var p =new Proxy(target,handler);p();//代理对象
3.4 has(target,key)
- 作用:用来拦截HasProperty操作,判断对象是否具有某个属性
- 参数:target:目标对象;key:需要查询的属性名
- 示例:
var handler={has(target,key){if(key[0]==='_'){return false}return key in target;}};var target={_prop:'jack',prop:'john' };var proxy =new Proxy(target,handler) 由于'_prop' in proxy中,所以返回结果为false,不会被in操作符发现
3.5 construct(target,args,newTarget)
- 作用:用于拦截new命令
- 参数:target:目标对象;args:构造函数的参数对象;newTarget:创建实例对象时,new命令作用的构造函数
- 注意:construct方法返回的必须是一个对象,否则会报错
- 示例:
var p =new Proxy(function(){},{construct: function(target,args){console.log('called'+args.join(','));return {value:args[0]*10}} }); console.log((new p(1)).value);//called1;10
3.6 deleteProperty(target,key)
- 作用:拦截delete操作,如果这个方法抛出错误或者返回false,当前属性就无法被delete删除
- 参数:target:目标对象;key:要删除的属性
- 示例:
var handler={deleteProperty(target,key){judge(key,'delete');delete targetp[key];return true;} }; function judge(key,action){if(key[0]==='_'){throw new Error('删除属性错误')} } var target={_prop:'foo'}; var proxy = new Proxy(target,handler); delete proxy._prop//报错,删除属性错误
3.7 getPropertyOf(target)
- 作用:拦截对代理对象原型链上属性的访问操作
- 参数:target:目标对象
- 示例:
const target={}; const proxy=new Proxy(target,{getPrototypeOf(target) {console.log('get prototype');return Object.getPrototypeOf(target)} }); console.log(Object.getPrototypeOf(proxy));//get prototype
3.8 setPrototypeOf(target,prototype)
-
作用:拦截对代理对象原型链上属性的设置操作
-
参数:target:目标对象;prototype:要设置的原型对象
-
示例:
const target ={}const proxy=new Proxy(target,{setPrototypeOf(target,prototype){console.log('set prototype');return Object.setPrototypeOf(target,prototype)}})const proto= {name:'jack'}Object.setPrototypeOf(proxy,proto)//set prototypeconsole.log(proxy.name);//jack