ES6的代理Proxy和反射Reflect
一、Proxy
Proxy(代理)
是 ES6 中新增的一個特性。Proxy 讓我們能夠以簡潔易懂的方式控制外部對物件的訪問。其功能非常類似於設計模式中的代理模式。
使用 Proxy 的好處
是:物件只需關注於核心邏輯,一些非核心的邏輯(如:讀取或設定物件的某些屬性前記錄日誌;設定物件的某些屬性值前,需要驗證;某些屬性的訪問控制等)可以讓 Proxy 來做。從而達到關注點分離,降級物件複雜度的目的。
https://www.jianshu.com/p/34f0e6abe312
使用語法:
var p = new Proxy(target, handler);
其中,target 為被代理物件。handler 是一個物件,其聲明瞭代理 target 的一些操作。p 是代理後的物件。
當外界每次對 p 進行操作時,就會執行 handler 物件上的一些方法。
handler 能代理的一些常用的方法如下:
1、
get(target,key)
:讀取2、
set(target,key,value)
:修改3、
has(target,key)
:判斷物件是否有該屬性4、
deleteProperty(target,key)
:刪除某個屬性5、
ownKeys(target)
:獲取所有的屬性名6、
construct
:建構函式…等等。
代理中把以 _ 開頭的變數都認為是私有的,不能進行讀取和修改。
還有些常用的方法例子和使用方式:
二、Reflect
Reflect(反射)是ES6為更方便的操作物件
而提供的新API 。
這個API設計的目的只要有:
1.將Object上明顯屬於語言內部的方法放到Reflect上
2.修改某些Object上方法的返回結果,使其變得合理
3.讓Object操作都變成函式行為。某些Object操作是命令式,比如name in obj和delete obj[name],而Reflect.has(obj, name)和Reflect.deleteProperty(obj, name)讓它們變成了函式行為。
4.Reflect物件的方法與Proxy物件的方法一一對應,只要是Proxy物件的方法,就能在Reflect物件上找到對應的方法。
這就讓Proxy物件可以方便地呼叫對應的Reflect方法,完成預設行為,作為修改行為的基礎。也就是說,不管Proxy怎麼修改預設行為,你總可以在Reflect上獲取預設行為。
Reflect物件一共有13個靜態方法:
Reflect.apply(target,thisArg,args)
Reflect.construct(target,args)
Reflect.get(target,key,receiver)
Reflect.set(target,key,value,receiver)
Reflect.defineProperty(target,key,desc)
Reflect.deleteProperty(target,key)
Reflect.has(target,key)
Reflect.ownKeys(target)
Reflect.isExtensible(target)
Reflect.preventExtensions(target)
Reflect.getOwnPropertyDescriptor(target, key)
Reflect.getPrototypeOf(target)
Reflect.setPrototypeOf(target, prototype)
上面這些方法的作用,大部分與Object物件的同名方法的作用都是相同的,而且它與Proxy物件的方法是一一對應的。
三、Proxy和Reflect的實際使用
對設定資料進行規則驗證:
// 定義一個校驗函式,返回代理物件
function validator(target,validator){
return new Proxy(target,{
_validator:validator,
set(target,key,value,proxy){
if(target.hasOwnProperty(key)){
let va=this._validator[key];
// 有這個屬性名並且設定的值符合校驗規則才能設定
if(!!va(value)){
return Reflect.set(target,key,value,proxy)
}else{
throw Error(`不能設定${key}為${value}`)
}
}else{
throw Error(`${key} 不存在`)
}
}
})
}
// 校驗規則
let personValidators={
name(val){
return typeof val==='string'
},
age(val){
return typeof val === 'number' && val > 18
}
}
class Person{
constructor(name,age){
this.name=name;
this.age=age;
// 傳入this類的例項,校驗規則
return validator(this,personValidators)
}
}
//例項化類Person
let person=new Person('xf',30);
console.info(person);
// person.name=22; //報錯,不讓設定
person.name='winne';
console.log(person);
這樣寫的好處:隨時能想驗證規則物件中新增驗證規則,然後在中新增屬性就可以了,用的時候就用,不用的時候也不需要管。方便擴充套件和提高可維護性。