1、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
上獲取默認行為。
2、Reflect.get
方法查找並返回target
對象的name
屬性,如果沒有該屬性,則返回undefined
。
3、Reflect.set
方法設置target
對象的name
屬性等於value
。如果name
屬性設置了賦值函數,則賦值函數的this
綁定receiver
。
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
4、Reflect.has
方法對應name in obj
里面的in
運算符。
5、Reflect.deleteProperty
方法等同於delete obj[name]
,用於刪除對象的屬性。
該方法返回一個布爾值。如果刪除成功,或者被刪除的屬性不存在,返回true
;刪除失敗,被刪除的屬性依然存在,返回false
。
6、Reflect.construct
方法等同於new target(...args)
,這提供了一種不使用new
,來調用構造函數的方法。
function Greeting(name) { this.name = name; } // new 的寫法 const instance = new Greeting('張三'); // Reflect.construct 的寫法 const instance = Reflect.construct(Greeting, ['張三']);
7、Reflect.defineProperty
方法基本等同於Object.defineProperty
,用來為對象定義屬性。未來,后者會被逐漸廢除,請從現在開始就使用Reflect.defineProperty
代替它。
8、觀察者模式(Observer mode)指的是函數自動觀察數據對象,一旦對象有變化,函數就會自動執行。
下面,使用 Proxy 寫一個觀察者模式的最簡單實現,即實現observable
和observe
這兩個函數。思路是observable
函數返回一個原始對象的 Proxy 代理,攔截賦值操作,觸發充當觀察者的各個函數。
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
之中,會自動執行所有觀察者。