ES6语法——Proxy、Reflect

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所擅长的事情

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章