Proxy --概述篇

 概述:es6

  Proxy 用於修改某些操做的默認行爲,等同於在語言層面作出修改,因此屬於一種「元編程」(meta programming),即對編程語言進行編程。
編程

  Proxy 能夠理解成,在目標對象以前架設一層「攔截」,外界對該對象的訪問,都必須先經過這層攔截,所以提供了一種機制,能夠對外界的訪問進行過濾和改寫。Proxy 這個詞的原意是代理,用在這裏表示由它來「代理」某些操做,能夠譯爲「代理器」。app

 

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

  上面代碼說明,Proxy 實際上重載(overload)了點運算符,即用本身的定義覆蓋了語言的原始定義。函數

 

 

  ES6 原生提供 Proxy 構造函數,用來生成 Proxy 實例。this

var proxy = new Proxy(target, handler);

  

  Proxy 對象的全部用法,都是上面這種形式,不一樣的只是handler參數的寫法。其中,new Proxy()表示生成一個Proxy實例,target參數表示所要攔截的目標對象handler參數也是一個對象,用來定製攔截行爲spa

 

  下面是另外一個攔截讀取屬性行爲的例子。prototype

var proxy = new Proxy({}, {
  get: function(target, property) {
    return 35;
  }
});

proxy.time // 35
proxy.name // 35
proxy.title // 35

  上面代碼中,做爲構造函數,Proxy接受兩個參數。第一個參數是所要代理的目標對象(上例是一個空對象),即若是沒有Proxy的介入,操做原來要訪問的就是這個對象;第二個參數是一個配置對象,對於每個被代理的操做,須要提供一個對應的處理函數,該函數將攔截對應的操做。好比,上面代碼中,配置對象有一個get方法,用來攔截對目標對象屬性的訪問請求。get方法的兩個參數分別是目標對象和所要訪問的屬性。能夠看到,因爲攔截函數老是返回35,因此訪問任何屬性都獲得35代理

  

 

  注意,要使得Proxy起做用,必須針對Proxy實例(上例是proxy對象)進行操做,而不是針對目標對象(上例是空對象)進行操做。code

  若是handler沒有設置任何攔截,那就等同於直接通向原對象。

var target = {};
var handler = {};
var proxy = new Proxy(target, handler);
proxy.a = 'b';
target.a // "b"

  上面代碼中,handler是一個空對象,沒有任何攔截效果,訪問proxy就等同於訪問target

 

 

  一個技巧是將 Proxy 對象,設置到object.proxy屬性,從而能夠在object對象上調用。

var object = { proxy: new Proxy(target, handler) };

   

  Proxy 實例也能夠做爲其餘對象的原型對象。

var proxy = new Proxy({}, {
  get: function(target, property) {
    return 35;
  }
});

let obj = Object.create(proxy);
obj.time // 35

  上面代碼中,proxy對象是obj對象的原型,obj對象自己並無time屬性,因此根據原型鏈,會在proxy對象上讀取該屬性,致使被攔截。

 

  同一個攔截器函數,能夠設置攔截多個操做。

var handler = {
  get: function(target, name) {
    if (name === 'prototype') {
      return Object.prototype;
    }
    return 'Hello, ' + name;
  },

  apply: function(target, thisBinding, args) {
    return args[0];
  },

  construct: function(target, args) {
    return {value: args[1]};
  }
};

var fproxy = new Proxy(function(x, y) {
  return x + y;
}, handler);

fproxy(1, 2) // 1
new fproxy(1,2) // {value: 2}
fproxy.prototype === Object.prototype // true
fproxy.foo // "Hello, foo"

 

轉自: ECMAScript 6 入門

做者:阮一峯

相關文章
相關標籤/搜索