Proxy和Reflect的用法
Proxy的用法
{
// 供应商,原始对象,存储真实的数据
let obj={
time:'2017-03-11',
name:'net',
_r:123
};
// 创建一个代理商,通过Proxy新生成一个对象monitor,代理obj的读写操作,用户访问的是monitor,不是直接操作obj这个对象
let monitor = new Proxy(obj,{
// 拦截对象属性的读取
get(target,key){
//通过代理把obj中的time的值中2017替换成了2018
return target[key].replace('2017','2018');
},
//拦截对象设置属性的值
set(target,key,value){
if(key === '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){
// key是time的就过滤掉
return Object.keys(target).filter(item=>itme!='time');
}
});
console.log('get',monitor.time);// get 2018-03-11
monitor.time = '2018';
monitor.name = 'haha';
console.log('set',monitor.time);// set 2018-03-11
console.log(monitor);// Proxy{time:'2017-03-11', name:'haha',
_r:123}
console.log('has','name' in monitor,'time' in monitor);// has true false
// 通过代理我们欺骗了用户,time属性肯定是obj的,但是我们过滤了,只暴露了name属性
//删除某些属性
delete monitor.time;
console.log('delete',monitor);//结果是 Proxy{time:'2017-03-11', name:'haha',
_r:123}
delete monitor._r;
console.log('delete',monitor);
// 结果是 Proxy{time:'2017-03-11', name:'haha'}
console.log('ownKeys',monitor);
// ["name","_r"]
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
Reflect的用法,不用new,而是直接使用,类似于对象的调用
{
let obj={
time:'2017-03-11',
name:'net',
_r:123
};
console.log('Reflect get',Reflect.get(obj,'time'));// 2017-03-11
Reflect.set(obj,'name','找');
console.log(obj);//结果是 Proxy{time:'2017-03-11', name:'找',
_r:123}
console.log('has',Reflect.has(obj,'name'));// true
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
2
3
4
5
6
7
8
9
10
11
12
13
14
通用方式使用,利用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 personValidator = {
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';
// 返回了一个proxy对象,代理了person对象,this就是Person的实例,返回的是对this的代理,属性就不能任意的修改了
return validator(this,personValidators)
}
}
const person=new Person('lilei',30)
console.info(person);// 结果是 Proxy{name:'lilei',age:30}
//person.name = 48;
// 会跑出一个错误 ,不能设置name到48
person.name = 'Han mei mei';
console.info(person);// 结果是 Proxy{name:'Han mei mei',age:30}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
