代理模式
资料来源JavaScript高级程序设计 使用代理可以在代码中实现一些有用的编程模式
跟踪属性访问
通过捕获get、set和has等操作,可以知道对象属性什么时候被访问、被查询。把实现相应捕获器的某个对象代理放到应用中,可以监控这个对象何时在何处被访问
const user={
name:'yihen'
}
const proxy=new Proxy(user,{
get(target,property,receiver){
console.log(`获取属性${property}`);
return Reflect.get(...arguments);
},
set(target,property,value,receiver){
console.log(`把属性${property}的值设置为${value}`);
return Reflect.set(...arguments);
}
})
console.log(proxy.name);
proxy.age=18;
隐藏属性
代理内部实现对外部代码是不可见的,因此要隐藏目标对象上的属性也是很容易的
const hiddenProperty=['name','age'];
const target={
name:'yihen',
age:18,
id:123456
}
const proxy=new Proxy(target,{
get(target,property,reveicer){
if(hiddenProperty.includes(property)){
console.log(`该属性不允许被访问`)
return undefined;
}
else{
return Reflect.get(...arguments);
}
},
set(target,property,value,reveicer){
if(hiddenProperty.includes(property)){
console.log(`该属性不允许被设置`)
return false;
}
else{
return Reflect.set(...arguments);
}
}
})
proxy.name;
proxy.name='T';
console.log(proxy.id)
函数与构造函数参数验证
跟保护和验证属性类似,也可对函数和构造函数参数进行审查。比如,可以让函数只接收某种类型的值:
class User {
constructor(id) {
this.id_=id;
}
}
const proxy=new Proxy(User,{
construct(target,argumentList,newTarget){
if(argumentList[0]===undefined){
throw '必须传入一个ID';
}
else{
console.log("创建成功")
return Reflect.construct(...arguments)
}
}
})
new proxy(1);
new proxy();
数据绑定与可观察对象
通过代理可以把运行中原本不相关的部分联系到一起。这样就可以实现各种模式,从而让不同的代码互操作
比如,可以将被代理的类绑定到一个全局实例中,让所有创建的实例都可以添加到这个集合中
const userList = [];
class User {
constructor(name) {
this._name = name;
}
}
const proxy = new Proxy(User, {
construct(target, argumentList, newTarget) {
const res = Reflect.construct(...arguments);
userList.push(res);
return res;
}
})
new proxy('yihen')
new proxy('yi')
new proxy('hen')
for (const item of userList) {
console.log(item)
}
|