1.跟踪属性访问
const user = {
name: 'Jake'
};
const proxy = new Proxy(user,{
get(target,property,receiver){
console.log(`Getting ${property}`);
return Reflect.get(...arguments);
},
set(target,property,value,receiver){
console.log(`Setting ${property} = ${value}`);
return Reflect.set(...arguments);
}
});
proxy.name;
proxy.age = 27;
- 通过get、set和has等操作,可以知道对象属性什么时候被访问、被查询。把实现相应捕获器的某个对象代理到应用中,可以监控这个对象何时在何处被访问过。
2.隐藏属性
const hiddenProperties = ['foo','bar'];
const targetObject = {
foo: 1,
bar: 2,
baz: 3
};
const proxy = new Proxy(targetObject,{
get(target,property){
if(hiddenProperties.includes(property)){
return undefined;
}else{
return Reflect.get(...arguments);
}
},
has(target,property){
if(hiddenProperties.includes(property)){
return false;
}else{
return Reflect.has(...arguments);
}
}
});
console.log(proxy.foo);
console.log(proxy.bar);
console.log(proxy.baz);
console.log('foo' in proxy)
console.log('bar' in proxy)
console.log('baz' in proxy)
- 代理的内部实现对外部代码是不可见的,因此要隐藏目标对象上的属性也轻而易举。
3.属性验证
const target = {
onlyNumbersGoHere:0
};
const proxy = new Proxy(target,{
set(target,property,value){
if(typeof value !== 'number'){
return false;
}else{
return Reflect.set(...arguments);
}
}
});
proxy.onlyNumberGoHere = 1;
console.log(proxy.onlyNumbersGoHere);
proxy.onlyNumbersGoHere = '2';
console.log(proxy.onlyNumbersGoHere);
1.因为所有赋值操作都会触发set捕获器,所以可以根据所赋的值决定是允许还是拒绝赋值。
4.函数与构造函数参数验证
function median(...nums){
return nums.sort()[Math.floor(nums.length/2)];
}
const proxy = new Proxy(median,{
apply(target,thisArg,argumentsList){
for(const arg of argumentsList){
if(typeof arg !== 'number'){
throw 'Non-number argument provided'
}
}
return Reflect.apply(...arguments);
}
})
console.log(proxy(4,7,1));
console.log(proxy(4,'7',1));
- 跟保护和验证对象属性类似,也可对函数和构造函数参数进行审查。比如,可以让函数只接收某种类型的值。
class User{
constructor(id){
this._id = id;
}
}
const proxy = new Proxy(User,{
construct(target,argumentsList,newTarget){
if(atgumentsList[0] === undefined){
throw 'User cannot be instantiated without id';
}else{
return Reflect.construct(...arguments);
}
}
});
new proxy(1);
new proxy();
- 可以要求实例化时必须给构造函数传参
5.数据绑定与可观察对象
const userList = [];
class User{
constructor(name){
this.name_ = name;
}
}
const proxy = new Proxy(User,{
construct(){
const newUser = Reflect.construct(...arguments);
userList.push(newUser);
return newUser;
}
});
new proxy('John');
new proxy('Jacob');
new proxy('Jingleheimerschmidt');
console.log(userList);
- 通过代理可以把运行中原本不相关的部分联系到一起。这样就可以实现各种模式,从而让不同的代码互相操作。
const userList = [];
function emit(newValue){
console.log(newValue);
}
const proxy = new Proxy(userList,{
set(target,property,value,receiver){
const result = Reflect.set(...arguments);
if(result){
emit(Reflect.get(target,property,receiver));
}
return result;
}
});
proxy.push('John');
proxy.push('Jacob');
- 可以把集合绑定到一个事件分派程序,每次插入新实例时都会发送消息。
|