ES6的代理模式
语法
1 |
|
- target: 使用 Proxy 包装的目标对象(可以是任何类型的对象,包括原生数组,函数,甚至另一个代理
- handle: 一个通常以函数作为属性的对象,用来定制拦截行为
1 |
|
代理只会对proxy
对象生效,原对象没有效果。
Handler 对象常用的方法
- has: in 操作符的捕捉器。
- get: 属性读取操作的捕捉器
- set: 属性读取操作的捕捉器
- deleteProperty: delete 操作符的捕捉器
- ownKeys: Object.getOwnPropertyNames 方法和 Object.getOwnPropertySymbols 方法的捕捉器。
- apply: 函数调用操作的捕捉器。
- construct: new 操作符的捕捉器
hander.get
用于代理目标对象的属性读取操作, 授受三个参数 get(target, propKey, ?receiver)
target 目标对象
propkey 属性名
receiver Proxy 实例本身
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16const person = {
like: "sing dance rap basketball"
}
const obj = new Proxy(person, {
get: function(target, propKey) {
if (propKey in target) {
return target[propKey];
} else {
throw new ReferenceError("Prop name \"" + propKey + "\" does not exist.");
}
}
})
obj.like // sing dance rap basketball
obj.cxk // Uncaught ReferenceError: Prop name "cxk" does not exist.
// 在读取代理目标的值时,如果有值则直接返回,没有值就抛出一个自定义的错误注意:
- 如果要访问的目标属性是不可写以及不可配置的,则返回的值必须与该目标属性的值相同
- 如果要访问的目标属性没有配置访问方法,即get方法是undefined的,则返回值必须为undefined
可撤消的Proxy
proxy 有一个唯一静态的方法,Proxy.revocable(target, handler)
, 可以用来创建一个可撤销的代理对象
该方法的返回值是一个对象,其结构为: {"proxy": proxy, "revoke": revoke}
- proxy 表示新生成的代理对象本身,和用一般方式 new Proxy(target, handler) 创建的代理对象没什么不同,只是它可以被撤销掉。
- revoke 撤销方法,调用的时候不需要加任何参数,就可以撤销掉和它一起生成的那个代理对象。
应用场景
校验器
使用
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
27const target = {
id: 123,
name: 'alice'
}
const validators = {
name(val) {
return typeof val === 'string'
},
id(val) {
return typeof val === 'number'
}
}
const createValidator = (target, validator) => {
return new Proxy(target, {
_validator: validator,
set(target, propkey, value, proxy) {
let validator = this._validator[propKey](value)
if (validator) {
return Reflect.set(target, propkey, value, proxy)
} else {
throw Error(`Cannot set ${propkey} to ${value}. Invalid type.`)
}
}
})
}私有属性
使用Proxy轻松实现私有属性拦截
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18let target = {
_id: 123
}
const proxy = new Proxy(target, {
get(target, propkey, proxy) {
if (propkey[0] === '_') {
throw Error(`${propkey} is restricted`)
}
return Reflect.get(target, propkey, proxy)
},
set(target, propkey, value, proxy) {
if(propkey[0] === '_'){
throw Error(`${propkey} is restricted`)
}
return Reflect.set(target, propkey, value, proxy)
}
})
本博客所有文章除特别声明外,均采用 CC BY-SA 4.0 协议 ,转载请注明出处!