一、Reflect
對象與Proxy
對象同樣,也是 ES6 爲了操做對象而提供的新 API。Reflect
對象的設計目的有這樣幾個。函數
Object
對象的一些明顯屬於語言內部的方法(好比Object.defineProperty
),放到Reflect
對象上。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)
讓它們變成了函數行爲。Reflect
對象的方法與Proxy
對象的方法一一對應,只要是Proxy
對象的方法,就能在Reflect
對象上找到對應的方法。這就讓Proxy
對象能夠方便地調用對應的Reflect
方法,完成默認行爲,做爲修改行爲的基礎。也就是說,無論Proxy
怎麼修改默認行爲,你總能夠在Reflect
上獲取默認行爲。二、Reflect.get
方法查找並返回target
對象的name
屬性,若是沒有該屬性,則返回undefined
。this
三、Reflect.set
方法設置target
對象的name
屬性等於value
。若是name
屬性設置了賦值函數,則賦值函數的this
綁定receiver
。spa
var myObject = { foo: 4, set bar(value) { return this.foo = value; }, }; var myReceiverObject = { foo: 0, }; Reflect.set(myObject, 'bar', 1, myReceiverObject); myObject.foo // 4 myReceiverObject.foo // 1
四、Reflect.has
方法對應name in obj
裏面的in
運算符。設計
五、Reflect.deleteProperty
方法等同於delete obj[name]
,用於刪除對象的屬性。代理
該方法返回一個布爾值。若是刪除成功,或者被刪除的屬性不存在,返回true
;刪除失敗,被刪除的屬性依然存在,返回false
。code
六、Reflect.construct
方法等同於new target(...args)
,這提供了一種不使用new
,來調用構造函數的方法。server
function Greeting(name) { this.name = name; } // new 的寫法 const instance = new Greeting('張三'); // Reflect.construct 的寫法 const instance = Reflect.construct(Greeting, ['張三']);
七、Reflect.defineProperty
方法基本等同於Object.defineProperty
,用來爲對象定義屬性。將來,後者會被逐漸廢除,請從如今開始就使用Reflect.defineProperty
代替它。對象
八、觀察者模式(Observer mode)指的是函數自動觀察數據對象,一旦對象有變化,函數就會自動執行。blog
下面,使用 Proxy 寫一個觀察者模式的最簡單實現,即實現observable
和observe
這兩個函數。思路是observable
函數返回一個原始對象的 Proxy 代理,攔截賦值操做,觸發充當觀察者的各個函數。get
const queuedObservers = new Set(); const observe = fn => queuedObservers.add(fn); const observable = obj => new Proxy(obj, {set}); function set(target, key, value, receiver) { const result = Reflect.set(target, key, value, receiver); queuedObservers.forEach(observer => observer()); return result; }
上面代碼中,先定義了一個Set
集合,全部觀察者函數都放進這個集合。而後,observable
函數返回原始對象的代理,攔截賦值操做。攔截函數set
之中,會自動執行全部觀察者。