JS Proxy

什么是Proxy

Proxy对象是es6中新增的内建对象。Proxy是一种代理,可以帮助我们完成很多事情,例如对数据的处理,对构造函数的处理,对数据的验证等。Proxy更像是一种拦截器,可以在我们访问对象之前添加一层拦截,过滤一些操作。

1
2
3
4
5
/*
* target 目标对象(可以是任何类型的对象,包括原生数组,函数,甚至是另一个代理)。
* handle 一个对象,其属性是操作对应的自定义函数。
*/
var p = new Proxy(target, handle);

基本操作

get(target, propKey, receiver):拦截对象属性的读取。

1
2
3
4
5
6
/*
* target 目标对象
* propKey 对象属性名
* proxy 实例本身(严格地说,是操作行为所针对的对象)
*/
get(target, propKey, receiver)
1
2
3
4
5
6
7
8
var obj = {name: 'Lucy'}
var p = new Proxy(obj,{
get: function(target, propKey, proxy){
return propKey === 'name' ? 'Hello ' + target[propKey] : target[propKey]
}
})

p.name // 'Hello Lucy'

如果一个属性是不可配置(configurable)且不可写(writable),则 Proxy 不能修改该属性。

set(obj, prop, value, receive)

1
2
3
4
5
6
7
/*
* target 目标对象
* key 属性名
* value 属性值
* receive 代理本身
*/
set: function(target, key, value,receive)
1
2
3
4
5
6
7
8
9
10
11
12
13
var obj = {age : 18}
var p = new Proxy(obj,{
set : function(target,key,value){
if(key === 'age'){
target[key] = Math.min(value,100);
}else{
target[key] = value;
}
}
})
p.age = 101;
p.age // 100
obj.age // 100

has(target, prop) :boolean

has 方法是针对 in 操作符的代理方法。

1
2
3
4
5
/*
* target 目标对象
* prop 需要检查是否存在的属性.
*/
has(target, prop)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
const handler1 = {
has (target, key) {
if (key[0] === '_') {
return false;
}
return key in target;
}
};

const monster1 = {
_secret: 'easily scared',
eyeCount: 4
};

const proxy1 = new Proxy(monster1, handler1);
console.log('eyeCount' in proxy1);
// expected output: true

console.log('_secret' in proxy1);
// expected output: false

console.log('_secret' in monster1);
// expected output: true

apply(target, thisArg, argumentsList)

apply() 方法用于拦截函数的调用。

1
2
3
4
5
6
7
/*
* target 目标对象
* key 属性名
* value 属性值
* receive 代理本身
*/
apply(target, thisArg, argumentsList)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
function sum(a, b) {
return a + b;
}

const handler = {
apply: function(target, thisArg, argumentsList) {
console.log(`Calculate sum: ${argumentsList}`);
// expected output: "Calculate sum: 1,2"

return target(argumentsList[0], argumentsList[1]) * 10;
}
};

var proxy1 = new Proxy(sum, handler);

console.log(sum(1, 2));
// expected output: 3
console.log(proxy1(1, 2));
// expected output: 30