Proxy 用於修改某些操做的默認行爲,等同於在語言層面作出修改,因此屬於一種「元編程」(meta programming),即對編程語言進行編程。編程
Proxy 能夠理解成,在目標對象以前架設一層「攔截」,外界對該對象的訪問,都必須先經過這層攔截,所以提供了一種機制,能夠對外界的訪問進行過濾和改寫。Proxy 這個詞的原意是代理,用在這裏表示由它來「代理」某些操做,能夠譯爲「代理器」。bash
var obj = new Proxy({}, {
get: function (target, key, receiver) {
console.log(`getting ${key}!`);
return Reflect.get(target, key, receiver);
},
set: function (target, key, value, receiver) {
console.log(`setting ${key}!`);
return Reflect.set(target, key, value, receiver);
}
});
複製代碼
上面代碼對一個空對象架設了一層攔截,重定義了屬性的讀取(get
)和設置(set
)行爲。這裏暫時先不解釋具體的語法,只看運行結果。對設置了攔截行爲的對象obj
,去讀寫它的屬性,就會獲得下面的結果。
編程語言
obj.count = 1
// setting count!
++obj.count
// getting count!
// setting count!
// 2複製代碼
ES6 原生提供 Proxy 構造函數,用來生成 Proxy 實例。函數
var proxy = new Proxy(target, handler);複製代碼
Proxy 對象的全部用法,都是上面這種形式,不一樣的只是handler
參數的寫法。其中,new Proxy()
表示生成一個Proxy
實例,target
參數表示所要攔截的目標對象,handler
參數也是一個對象,用來定製攔截行爲。
ui
var proxy = new Proxy({}, {
get: function(target, property) {
return 35;
}
});
proxy.time // 35
proxy.name // 35
proxy.title // 35複製代碼
一、將Object
對象的一些明顯屬於語言內部的方法(好比Object.defineProperty
),放到Reflect
對象上。現階段,某些方法同時在Object
和Reflect
對象上部署,將來的新方法將只部署在Reflect
對象上。也就是說,從Reflect
對象上能夠拿到語言內部的方法。spa
二、修改某些Object
方法的返回結果,讓其變得更合理。好比,Object.defineProperty(obj, name, desc)
在沒法定義屬性時,會拋出一個錯誤,而Reflect.defineProperty(obj, name, desc)
則會返回false
。代理
三、讓Object
操做都變成函數行爲。某些Object
操做是命令式,好比name in obj
和delete obj[name]
,而Reflect.has(obj, name)
和Reflect.deleteProperty(obj, name)
讓它們變成了函數行爲。code
四、Reflect
對象的方法與Proxy
對象的方法一一對應,只要是Proxy
對象的方法,就能在Reflect
對象上找到對應的方法。這就讓Proxy
對象能夠方便地調用對應的Reflect
方法,完成默認行爲,做爲修改行爲的基礎。也就是說,無論Proxy
怎麼修改默認行爲,你總能夠在Reflect
上獲取默認行爲。對象
Proxy(target, {
set: function(target, name, value, receiver) {
var success = Reflect.set(target,name, value, receiver);
if (success) {
log('property ' + name + ' on ' + target + ' set to ' + value);
}
return success;
}
});
複製代碼
上面代碼中,Proxy
方法攔截target
對象的屬性賦值行爲。它採用Reflect.set
方法將值賦值給對象的屬性,確保完成原有的行爲,而後再部署額外的功能。
部署