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