Proxy(代理) 是 ES6 中新增的一个特性。Proxy 让我们能够以简洁易懂的方式控制外部对对象的访问。其功能非常类似于设计模式中的代理模式。
使用 Proxy 的好处是:对象只需关注于核心逻辑,一些非核心的逻辑(如:读取或设置对象的某些属性前记录日志;设置对象的某些属性值前,需要验证;某些属性的访问控制等)可以让 Proxy 来做。从而达到关注点分离,降级对象复杂度的目的。
使用方法
var p = new Proxy(target,handler)
其中,target 为被代理对象。handler 是一个对象,其声明了代理 target 的一些操作。p 是代理后的对象。
当外界每次对 p 进行操作时,就会执行 handler 对象上的一些方法。handler 能代理的一些常用的方法如下:
get:读取
set:修改
has:判断对象是否有该属性
construct:构造函数
...
var target={
name:'obj'
}
var logHandler={
get:function(target,key){
console.log(`${key}被读取`)
return target[key];
},
set:function(target,key,value){
console.log(`${key}被设置为${value}`)
target[key]=value;
}
}
var targetWithLog = new Proxy(target,logHandler);
在上面的 demo 中,
targetWithLog 读取属性的值时,实际上执行的是 logHandler.get :在控制台输出信息,并且读取被代理对象 target 的属性。
在 targetWithLog 设置属性值时,实际上执行的是 logHandler.set :在控制台输出信息,并且设置被代理对象 target 的属性的值。
实现虚拟属性
下面的 demo,虚拟了 fullName 这个属性。
var person={
firstName:'张',
lastName:'小白'
}
var proxyedPerson = new Proxy(person,{
get:function(target,key){
if(key==='fullName'){
return [target.firstName,target.lastName].join(' ');
}
return target[key];
},
set:function(target,key,value){
if(key==='fullName'){
var fullNameInfo = value.split(' ');
target.firstName = fullNameInfo[0];
target.lastName = fullNameInfo[1];
}else{
target[key]=value;
}
}
})
实现私有变量
下面的 demo 实现了真正的私有变量。代理中把以 _ 开头的变量都认为是私有的。
var api={
_secret:'xxxx',
_otherSec:'bbb',
ver:'v0.0.1'
}
api = new Proxy(api,{
get:function(target,key){
if(key.startsWith('_')){
console.log('私有变量不能被访问');
return false;
}
return target[key];
},
set:function(target,key,value){
if(key.startsWith('_')){
console.log('私有变量不能被修改');
return false;
}
target[key]=value;
},
has:function(target,key){
return key.startsWith('_')?false:(key in target);
}
})
抽离校验模块
下面的 demo 实现了在代理中实现设置属性值前做验证。
function Animal(){
return createValidator(this,animalValidator)
}
var animalValidator = {
name:function(name){
return typeof name==='string';
}
}
function createValidator(target,validator){
return new Proxy(target,{
set:function(target,key,value){
if(validator[key]){
if(validator[key](value)){
console.log(validator[key](value))
target[key]=value;
}else{
throw Error(`Cannot set ${key} to ${values}.Invalid.`);
}
}else{
target[key]=value;
}
}
})
}
var dog = new Animal();
dog.name = 'dog'
源码地址:https://blog.csdn.net/sinat_17775997/article/details/84233822