1. Proxy代理
// 供应商(原始对象)
let obj = {
time:'2018-01-03',
name:'net',
_r: "123"
}
// 创建代理商,传入obj数据
let monitor = new Proxy(obj,{
get(target,key){ // 拦截对象属性的读取 target是传入的对象obj
return target[key].replace('2017','2018');
},
set(target,key,value){ // 拦截对象设置属性
if(key === 'name'){
return target[key] = value;
}else{
return target[key];
}
},
has(target,key){ // 拦截key in object 操作
if(key ==='name'){
return target[key]
}else{
return false;
}
},
deleteProperty(target,key){ // 拦截delete 除了_r属性能删除,其他不行
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');
}
});
// 用户获取
console.log('get',monitor.time); // get 2018-01-03
monitor.time = '2019';
console.log('get',monitor.name); // get net
console.log('set',monitor.time); // set 2018-01-03 代理拦截的只能设置name属性
monitor.name = 'yiteer';
console.log('set',monitor.name); // set yiteer name属性设置成功
// 拦截key in object 操作欺骗了用户,代理设置name是obj的属性,其他不是
console.log('has','name' in monitor,'time' in monitor); //has true false
// 删除time属性
delete monitor.time;
console.log('delete_time',monitor.time); // delete_time 2018-01-03
// 删除_r属性
delete monitor._r;
console.log('delete_r' , monitor._r) // undefined
// 过滤属性名不是time的属性
console.log('ownKeys',Object.keys(monitor)); // ["name", "_r"]
}
2. Reflect反射(反射的是obj)
Reflect 的特性和Proxy的用法非常类似 不用new一个实例, 直接用即可
// 供应商(原始对象)
let obj = {
time:'2018-01-03',
name:'net',
_r: "123"
}
// 获取对象的值
console.log('Reflect get',Reflect.get(obj,'time')); // Reflect get 2018-01-03
// 设置对象的值
Reflect.set(obj,'name','xiaxiaoxian');
console.log(obj); // {time: "2018-01-03", name: "xiaxiaoxian", _r: "123"}
// 判断对象是否拥有某个属性
console.log('has',Reflect.has(obj,'name')) // has true
3. 利用Proxy代理创建一个信息校验的函数
function validator(target,validator){
return new Proxy(target,{ // target指person的实例
_validator:validator,
set(target,key,value,proxy){ // 代理对set有限制
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,mobile){
this.name = name;
this.age = age;
this.mobile = '13735872697'
return validator(this,personValidators); // this是person的实例,但是被代理了
}
}
// 实例化一个对象
const person = new Person('lilei',30);
console.log(person); //{name: "lilei", age: 30, mobile: "13735872697"}
// 修改
//person.name = 48; //报错 : 不能设置name到48
person.name = 'xiaxaioxian';
//person.age = 17; // 报错 :Uncaught Error: 不能设置age到17
//person.class = '304班'; // 报错: Uncaught Error: class 不存在
console.info(person); // {name: "xiaxaioxian", age: 30, mobile: "13735872697"}