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之中,會自動執行所有觀察者。
