Proxy(代理) 是 ES6 中新增的一個特性卢厂。Proxy 讓我們能夠以簡潔易懂的方式控制外部對對象的訪問乾蓬。其功能非常類似于設(shè)計模式中的代理模式。
使用 Proxy 的好處是:對象只需關(guān)注于核心邏輯慎恒,一些非核心的邏輯(如:讀取或設(shè)置對象的某些屬性前記錄日志任内;設(shè)置對象的某些屬性值前,需要驗證巧号;某些屬性的訪問控制等)可以讓 Proxy 來做族奢。從而達(dá)到關(guān)注點分離,降級對象復(fù)雜度的目的丹鸿。
使用方法
var p = new Proxy(target,handler)
其中越走,target 為被代理對象。handler 是一個對象靠欢,其聲明了代理 target 的一些操作廊敌。p 是代理后的對象。
當(dāng)外界每次對 p 進(jìn)行操作時门怪,就會執(zhí)行 handler 對象上的一些方法骡澈。handler 能代理的一些常用的方法如下:
get:讀取
set:修改
has:判斷對象是否有該屬性
construct:構(gòu)造函數(shù)
...
var target={
name:'obj'
}
var logHandler={
get:function(target,key){
console.log(`${key}被讀取`)
return target[key];
},
set:function(target,key,value){
console.log(`${key}被設(shè)置為${value}`)
target[key]=value;
}
}
var targetWithLog = new Proxy(target,logHandler);
在上面的 demo 中,
targetWithLog 讀取屬性的值時掷空,實際上執(zhí)行的是 logHandler.get :在控制臺輸出信息肋殴,并且讀取被代理對象 target 的屬性。
在 targetWithLog 設(shè)置屬性值時坦弟,實際上執(zhí)行的是 logHandler.set :在控制臺輸出信息护锤,并且設(shè)置被代理對象 target 的屬性的值。
實現(xiàn)虛擬屬性
下面的 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;
}
}
})
實現(xiàn)私有變量
下面的 demo 實現(xiàn)了真正的私有變量。代理中把以 _ 開頭的變量都認(rèn)為是私有的赤炒。
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);
}
})
抽離校驗?zāi)K
下面的 demo 實現(xiàn)了在代理中實現(xiàn)設(shè)置屬性值前做驗證氯析。
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