My Little World

关于代理proxy

代理是JS es6中引入,可用于控制对象
—代理可以定制对象交互时行动(例如,当读取属性或调用方法)
— 所有交互行为都必须通过代理,指定的行为发生时会调用代理方法
使用代理可以优雅实现以下内容

  • 日志记录
  • 性能测试
  • 数据校验
  • 自动填充对象属性
  • 数组负索引

使用代理对对象访问添加日志 — report 函数用于添加日志

1
2
3
4
5
6
7
8
9
10
11
12
function makeLoggable(target){
return new Proxy(target,{
get:(target,property)=>{
report('READING:'+property)
return target[property]
},
set:(target,property,value)=>{
report('writing value' +value +'to'+'property')
target[property] = value
}
})
}

proxy 用于数据校验

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
var personValidator = {
name(val){
return typeof val === 'string'
}
age(val){
return typeof val === 'number' && val>18
}
}
class person{
constructor(name,age){
this.name = name;
this.age = age;
return createValidator(this,personValidator)
}
}
function createValidator(target,validator){
return new Proxy(target,{
_validator:validator,
set(target,key,value,proxy){
if(target.hasOwnproperty(key)){
var validator = this._validator[key]
if(validator(value)){
return Reflect.set(target,key,value,proxy)
}else{
throw Error('type error')
}
}
}
})
}

使用代理自动填充属性

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
function Folder(){
return new Proxy({},{
get:(target,property)=>{
if(!(property in target)){
target[property] = new Folder()
}
return target[property]
}
})
}

const rootFolder = new Folder()
try {
rootFolder.ninjasDir.firstNinjaDir.ninjaFile = 'yoshi.txt'
}catch(e){
console.log(e)
}

使用代理实现数组负引用

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
function creatNegativeArrayProxy(array){
if(!Array.isArray(array)){
throw new TypeError('expected an array')
}
return new Proxy(array,{
get:(target,index)=>{
index = +index
return target[index<0?target.length+index:index]
},
set:(target,index,val)=>{
index = +index
return target[index<0?target.length+index:index] = val
}
})
}

const ninja = [1,2,3]
const proxi = creatNegativeArrayProxy(ninja)
console.log(proxi[-1]) //==> 3
proxi[-2] = 22 // ninja ==>1,22,3