Proxy 可以理解成,在目标对象之前架设一层“拦截”,外界对该对象的访问,都必须先通过这层拦截,因此提供了一种机制,可以对外界的访问进行过滤和改写。Proxy 这个词的原意是代理,用在这里表示由它来“代理”某些操作,可以译为“代理器”。
1 { 2 //类似于供应商的数据对象 3 let obj = { 4 time:'2019-12-13', 5 name:'net', 6 _r:123 7 } 8 //代理商 9 let monitor = new Proxy(obj,{ 10 //代理操作 11 //拦截对象属性的读取 12 get(target,key){ //target指代理对象,key是键值 13 return target[key].replace('2019','2020') 14 }, 15 // 拦截对象设置 16 set(target,key,value){ 17 if(key === 'name'){ 18 return target[key] = value; 19 }else{ 20 return target[key]; 21 } 22 }, 23 // 拦截 key in object 操作 24 has(target,key){ 25 if(key === 'name'){ 26 return target[key] 27 }else{ 28 return false; 29 } 30 }, 31 // 拦截删除 32 deleteProperty(target,key){ 33 if(key.indexOf('_') > -1){ 34 delete target[key]; 35 return true; 36 }else{ 37 return target[key] 38 } 39 }, 40 // 拦截Object.keys,Object.getOwnPropertySymbols,Object.getOwnPropertyNames 41 ownKeys(target){ 42 return Object.keys(target).filter(item=>item!='time') //Object.keys(target)取出原始对象的key值 43 } 44 }); 45 //用户直接操作minotor 46 console.log('get',monitor.time) 47 48 monitor.time='2019'; 49 monitor.name='sss'; 50 console.log('set',monitor.time,monitor) 51 52 console.log('has','name' in monitor,'time' in monitor) //true false 53 54 // delete monitor.time; 55 // console.log('delete',monitor) 56 57 // delete monitor._r; 58 // console.log('delete',monitor) 59 60 console.log('ownkeys',Object.keys(monitor)) //过滤属性 61 62 }
Reflect
1 { 2 let obj = { 3 time:'2019-12-13', 4 name:'net', 5 _r:123 6 }; 7 console.log('reflect get',Reflect.get(obj,'time')); //Reflect 不需要new, get语法,对象,key值 8 Reflect.set(obj,'name','bsq'); 9 console.log('set',obj) 10 11 console.log('has',Reflect.has(obj,'name')) 12 }
实例运用
1 { 2 // 应用 3 function validator(target,validator){ 4 return new Proxy(target,{ 5 _validator:validator, 6 set(target,key,value,proxy){ 7 if(target.hasOwnProperty(key)){ 8 let va = this._validator[key]; 9 if(!!va(value)){ 10 return Reflect.set(target,key,value,proxy); 11 }else{ 12 throw Error(`不能设置${key}为${value}`) 13 } 14 }else{ 15 throw Error(`${key} 不存在`) 16 } 17 } 18 }) 19 } 20 const personValidators={ 21 name(val){ 22 return typeof val === 'string' 23 }, 24 age(val){ 25 return typeof val ==='number' && val>18 26 } 27 } 28 class Person{ 29 constructor(name,age){ 30 this.name=name; 31 this.age=age; 32 return validator(this,personValidators) 33 } 34 } 35 const person = new Person('lilei',30); 36 console.log(person) 37 // person.age='dd'; 38 // console.log(person) //index.js:9736 Uncaught Error: 不能设置age为dd 39 person.name='han meimei' 40 console.log(person) 41 }