ES6(Proxy和Reflect)
2019-03-29 本文已影响0人
陈裔松的技术博客
Proxy
代理,用于连接用户与真实的对象。通过代理,可以根据不同的业务逻辑,做相应的处理。
// 目标对象
let obj = {
time: '2017-03-11',
name: 'net',
_r: 123
}
// 新建一个代理,代理对象:obj
let monitor = new Proxy(obj, {
// 拦截对目标对象属性的读取
// target:目标对象(obj),key:想要读取的属性
get(target, key) {
return target[key].replace('2017', '2018');
},
// 拦截对目标对象属性的设置
// target:目标对象(obj),key:想要设置的属性,value:想要设置的值
set(target, key, value) {
// 自定义限制:只允许修改name属性
if (key === 'name') {
return target[key] = value;
} else {
return target[key];
}
},
// 拦截key in object操作
has(target, key) {
// 自定义限制:只暴露name属性
if (key === 'name') {
return target[key];
} else {
return false;
}
},
// 拦截对目标对象属性的删除
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');
}
});
console.log(monitor.time); // 2018-03-11 2017已经被替换成2018
monitor.time = '2018';
console.log(monitor.time); // 2018-03-11 修改time属性失败
monitor.name = 'song';
console.log(monitor.name); // song 修改name属性成功
console.log('name' in monitor); // true 暴露
console.log('time' in monitor); // false 未暴露
delete monitor.time;
console.log(monitor); // Proxy {time: "2017-03-11", name: "song", _r: 123}
delete monitor._r;
console.log(monitor); // Proxy {time: "2017-03-11", name: "song"}
console.log(Object.keys(monitor)); // ["name"]
Reflect
映射,用于映射真实的对象。其拥有的方法与Proxy的方法完全一致。
let obj = {
time: '2017-03-11',
name: 'net',
_r: 123
}
console.log(Reflect.get(obj, 'name')); // net
Reflect.set(obj, 'name', 'song');
console.log(Reflect.get(obj, 'name')); // song
console.log(Reflect.has(obj, 'name')); // true
使用场景(数据校验)
// 与传统校验方式相比,这种方式把校验规则单独抽离出来,减少与业务逻辑的耦合
// 通用代理生成函数
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;
}
}
// 类Person实例化之后,得到的是一个对Person实例对象的代理
class Person {
constructor(name, age) {
this.name = name;
this.age = age;
return validator(this, personValidators); // this指向的是类的实例
}
}
const person = new Person('lilei', 30);
console.log(person); // Proxy {name: "lilei", age: 30}
person.name = 48; // Uncaught Error: 不能设置name到48