ES6 (7):Reflect

Reflect 配合proxy  使對象的操做更加函數化。javascript

大部分Reflect 的全局方法或者說靜態方法與proxy一致。java

相比Object  返回值更合理:修改某些Object方法的返回結果,讓其變得更合理。好比,Object.defineProperty(obj, name, desc)在沒法定義屬性時,會拋出一個錯誤,而Reflect.defineProperty(obj, name, desc)則會返回falseapp

 

若是 Proxy對象和 Reflect對象聯合使用,前者攔截賦值操做,後者完成賦值的默認行爲,並且傳入了receiver,那麼Reflect.set會觸發Proxy.defineProperty攔截。函數

let p = {
  a: 'a'
};

let handler = {
  set(target, key, value, receiver) {
    console.log('set');
    Reflect.set(target, key, value, receiver)
  },
  defineProperty(target, key, attribute) {
    console.log('defineProperty');
    Reflect.defineProperty(target, key, attribute);
  }
};

let obj = new Proxy(p, handler);
obj.a = 'A';
// set
// defineProperty

 由於Proxy.setreceiver參數老是指向當前的 Proxy實例(即上例的obj),而Reflect.set一旦傳入receiver,就會將屬性賦值到receiver上面(即obj),致使觸發defineProperty攔截。若是Reflect.set沒有傳入receiver,那麼就不會觸發defineProperty攔截。this

 

 

Reflect.construct: 等同於new  target(args) 建立實例對象。spa

function Greeting(name) {
  this.name = name;
}

// new 的寫法
const instance = new Greeting('張三');

// Reflect.construct 的寫法
const instance = Reflect.construct(Greeting, ['張三']);

 若是Reflect.construct()方法的第一個參數不是函數會報錯prototype

 

Reflect.getPrototypeOf:用於讀取對象的__proto__屬性,對應Object.getPrototypeOf(obj)代理

const myObj = new FancyThing();

// 舊寫法
Object.getPrototypeOf(myObj) === FancyThing.prototype;

// 新寫法
Reflect.getPrototypeOf(myObj) === FancyThing.prototype;

 Reflect.getPrototypeOfObject.getPrototypeOf的一個區別是,若是參數不是對象,Object.getPrototypeOf會將這個參數轉爲對象,而後再運行,而Reflect.getPrototypeOf會報錯code

 

 

Reflect.apply(): 若是要綁定一個函數的this對象,能夠這樣寫fn.apply(obj, args),可是若是函數定義了本身的apply方法,就只能寫成Function.prototype.apply.call(fn, obj, args),採用Reflect對象能夠簡化這種操做。server

 

Reflect.defineProperty:爲對象定義屬性

const p = new Proxy({}, {
  defineProperty(target, prop, descriptor) {
    console.log(descriptor);
    return Reflect.defineProperty(target, prop, descriptor);
  }
});

p.foo = 'bar';
// {value: "bar", writable: true, enumerable: true, configurable: true}

p.foo // "bar"

 Proxy.defineProperty對屬性賦值設置了攔截,而後使用Reflect.defineProperty完成了賦值

 

 

Reflect.preventExtensions:用於讓一個對象變爲不可擴展。它返回一個布爾值,表示是否操做成功。

 

觀察者模式:使用 Proxy 寫一個觀察者模式的最簡單實現,即實現observableobserve這兩個函數。思路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;
}

 首先:須要定義observable ,定義代理(添加須要被代理的對象),在執行set(例子中爲set 對象的add 添加)操做時,代理對象首先在目標對象(原始對象)設置屬性與值,而後循環執行觀察者函數(例子中print方法)。

const person = observable({
  name: '張三',
  age: 20
});

function print() {
  console.log(`${person.name}, ${person.age}`)
}

observe(print);
person.name = '李四';
// 輸出
// 李四, 20
相關文章
相關標籤/搜索