一.什么是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//jack
proxy.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 prototype console.log(proxy.name);//jack