ES6的Proxy和Reflect

一:Proxy

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複製代碼

二:Reflect

一、將Object對象的一些明顯屬於語言內部的方法(好比Object.defineProperty),放到Reflect對象上。現階段,某些方法同時在ObjectReflect對象上部署,將來的新方法將只部署在Reflect對象上。也就是說,從Reflect對象上能夠拿到語言內部的方法。spa

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

三、讓Object操做都變成函數行爲。某些Object操做是命令式,好比name in objdelete 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方法將值賦值給對象的屬性,確保完成原有的行爲,而後再部署額外的功能。
部署

相關文章
相關標籤/搜索