Proxy、Reflect
Proxy和Reflect的概念
Proxy和Reflect的使用场景
Proxy (代理即拦截)
- 代理
{
//obj作为原始对象,原始对象存储真实数据
//通过new Proxy() 新生成一个对象,这个对象映射obj,让它在中间做一些操作
//最后用户访问的是monitor,不管用户是设置monitor还是读取monitor属性,最终通过Proxy传递给obj
let obj = {
time: '2017-03-11',
name: 'net',
_r: 123
}
//Proxy作为中间代理层,也叫拦截层
//Proxy第一参数:需要代理的对象
//Proxy第二参数:存放方法,实现真正要代理的东西
let monitor = new Proxy(obj,{
//拦截(即代理)对象属性的读取
get(target,key){//get的时候就是拦截读取的属性
return target[key].replace('2017','2018')
},
//拦截对象设置属性
set(target,key,value){//target是代理对象,key:代理对象的属性,value:代理对象的属性值
if(key==='name'){//只允许修改name属性
return target[key]=value;
}else{
return target[key]
}
},
//拦截key in object操作
has(target,key){
if(key === 'name'){
return target[key]
}else{
return false
}
},
//拦截delete
deleteProperty(target,key){
//属性以_开头的,可以删除,不然不能删除
if(key.indexOf('_')>-1){
delete target[key];
return true;
}else{
return target[key]
}
},
//拦截Object.keys , Object.getOwnPropertySymbols , Object.getOwnPropertyNames
ownKeys(target){
return Object.keys(target).filter(item=>item!='time')
//过滤的时候把time保护起来了
}
});
//对用户而言,直接操作monitor对象
console.log('get',monitor.time);//从monitor中读取time属性
monitor.time = '2019';
monitor.name = '七七七';
console.log('Proxy',monitor)
}
//拦截key in object操作
console.log('has','name' in monitor, 'time' in monitor);//true false //time在obj里,但代理做了处理,这相当于欺骗了用户
//拦截delete
delete monitor.time;
console.log('delete',monitor);//未删除
detele monitor._r;
console.log('delete',monitor);//已删除
//拦截Object.keys , Object.getOwnPropertySymbols , Object.getOwnPropertyNames
console.log('ownKeys',Object.keys(monitor));//把time保护起来了
Reflect (反射)
- Reflect 用法和Proxy类似
let obj = {
time: '2017-03-11',
name: 'net',
_r: 123
};
//Reflect(target,key,value)类似与Proxy的参数
console.log('Reflect get',Reflect.get(obj,'time'));
//读取
Reflect.set(obj,'name','哈哈哈');//设置
console.log(obj);
//判断obj是否有name属性
console.log('has',Reflect.has(obj,'name'));//true
Proxy和Reflect的使用场景
- 开发过程中的校验
- 例如年龄范围
- 例如提交的时候数据类型
- 例如手机号格式校验
//使用Proxy、Reflect 进行解耦,和业务解耦的校验模块
{
function validator(target,validator){
return new Proxy(target,{
_validator: validator,
set(target,key,value,proxy){
if(target.hasOwnProperty(key)){
let va=this._validator[key];
if(!!va(value)){
return Reflect.set(target,key,value,proxy)
}else{
throw Error(`不能设置${key}到${value}`)
}
}else{
throw Error(`${key} 不存在`)
}
}
})
}
const personValidators={
name(val){
return typeof val==='string'
},
age(val){
return typeof val=== 'number' && val>18
},
//mobile(val){//后期扩展
//......
//}
}
class Person{
constructor(name,age){
this.name=name;
this.age=age;
//this.mobile='1111';//后期进行扩展
return validator(this,personValidators)
}
}
const person=new Person('lilei',30);
console.info(person);
person.name=48;
person.name = 'hanmeimei'
}
通过代理的方式,把条件和对象本身(即业务逻辑)完全进行隔离
后期进行扩展的话,比如mobile
代码的整洁度、维护性、复用性、健壮性都非常强
数据校验就是Proxy所擅长的事情