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

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