中文字幕免费精品_亚洲视频自拍_亚洲综合国产激情另类一区_色综合咪咪久久

詳細探究ES6之Proxy代理
來源:易賢網 閱讀:1031 次 日期:2016-07-29 14:56:28
溫馨提示:易賢網小編為您整理了“詳細探究ES6之Proxy代理”,方便廣大網友查閱!

ES6中提出了一個新的特性,就是proxy,用來攔截在一個對象上的指定操作,這個功能非常的有用。本文會介紹 Proxy的使用方式及列舉具體實例解釋 Proxy 的使用場景。

前言

在ES6中,Proxy構造器是一種可訪問的全局對象,使用它你可以在對象與各種操作對象的行為之間收集有關請求操作的各種信息,并返回任何你想做的。ES6中的箭頭函數、數組解構、rest 參數等特性一經實現就廣為流傳,但類似 Proxy 這樣的特性卻很少見到有開發者在使用,一方面在于瀏覽器的兼容性,另一方面也在于要想發揮這些特性的優勢需要開發者深入地理解其使用場景。就我個人而言是非常喜歡 ES6 的 Proxy,因為它讓我們以簡潔易懂的方式控制了外部對對象的訪問。在下文中,首先我會介紹 Proxy 的使用方式,然后列舉具體實例解釋 Proxy 的使用場景。

Proxy,見名知意,其功能非常類似于設計模式中的代理模式,該模式常用于三個方面:

1.和監視外部對對象的訪問

2.函數或類的復雜度

3.操作前對操作進行校驗或對所需資源進行管理

在支持 Proxy 的瀏覽器環境中,Proxy 是一個全局對象,可以直接使用。Proxy(target, handler) 是一個構造函數,target 是被代理的對象,handlder 是聲明了各類代理操作的對象,最終返回一個代理對象。外界每次通過代理對象訪問 target 對象的屬性時,就會經過 handler 對象,從這個流程來看,代理對象很類似 middleware(中間件)。那么 Proxy 可以攔截什么操作呢?最常見的就是 get(讀取)、set(修改)對象屬性等操作,完整的可攔截操作列表請點擊這里。此外,Proxy 對象還提供了一個 revoke 方法,可以隨時注銷所有的代理操作。在我們正式介紹 Proxy 之前,建議你對 Reflect 有一定的了解,它也是一個 ES6 新增的全局對象。

Basic

const target = { 

  name: 'Billy Bob',

  age: 15

};

const handler = { 

  get(target, key, proxy) {

    const today = new Date();

    console.log(`GET request made for ${key} at ${today}`);

    return Reflect.get(target, key, proxy);

  }

};

const proxy = new Proxy(target, handler);

proxy.name;

// => "GET request made for name at Thu Jul 21 2016 15:26:20 GMT+0800 (CST)"

// => "Billy Bob"

在上面的代碼中,我們首先定義了一個被代理的目標對象 target,然后聲明了包含所有代理操作的 handler 對象,接下來使用 Proxy(target, handler) 創建代理對象 proxy,此后所有使用 proxy 對 target 屬性的訪問都會經過 handler 的處理。

1. 抽離校驗模塊

讓我們從一個簡單的類型校驗開始做起,這個示例演示了如何使用 Proxy 保障數據類型的準確性:

let numericDataStore = { 

  count: 0,

  amount: 1234,

  total: 14

};

numericDataStore = new Proxy(numericDataStore, { 

  set(target, key, value, proxy) {

    if (typeof value !== 'number') {

      throw Error("Properties in numericDataStore can only be numbers");

    }

    return Reflect.set(target, key, value, proxy);

  }

});

// 拋出錯誤,因為 "foo" 不是數值

numericDataStore.count = "foo";

// 賦值成功

numericDataStore.count = 333;

如果要直接為對象的所有屬性開發一個校驗器可能很快就會讓代碼結構變得臃腫,使用 Proxy 則可以將校驗器從核心邏輯分離出來自成一體:

function createValidator(target, validator) { 

  return new Proxy(target, {

    _validator: validator,

    set(target, key, value, proxy) {

      if (target.hasOwnProperty(key)) {

        let validator = this._validator[key];

        if (!!validator(value)) {

          return Reflect.set(target, key, value, proxy);

        } else {

          throw Error(`Cannot set ${key} to ${value}. Invalid.`);

        }

      } else {

        throw Error(`${key} is not a valid property`)

      }

    }

  });

}

const personValidators = { 

  name(val) {

    return typeof val === 'string';

  },

  age(val) {

    return typeof age === 'number' && age > 18;

  }

}

class Person { 

  constructor(name, age) {

    this.name = name;

    this.age = age;

    return createValidator(this, personValidators);

  }

}

const bill = new Person('Bill', 25);

// 以下操作都會報錯

bill.name = 0; 

bill.age = 'Bill'; 

bill.age = 15;

通過校驗器和主邏輯的分離,你可以無限擴展 personValidators 校驗器的內容,而不會對相關的類或函數造成直接破壞。更復雜一點,我們還可以使用 Proxy 模擬類型檢查,檢查函數是否接收了類型和數量都正確的參數:

let obj = { 

  pickyMethodOne: function(obj, str, num) { /* ... */ },

  pickyMethodTwo: function(num, obj) { /*... */ }

};

const argTypes = { 

  pickyMethodOne: ["object", "string", "number"],

  pickyMethodTwo: ["number", "object"]

};

obj = new Proxy(obj, { 

  get: function(target, key, proxy) {

    var value = target[key];

    return function(...args) {

      var checkArgs = argChecker(key, args, argTypes[key]);

      return Reflect.apply(value, target, args);

    };

  }

});

function argChecker(name, args, checkers) { 

  for (var idx = 0; idx < args.length; idx++) {

    var arg = args[idx];

    var type = checkers[idx];

    if (!arg || typeof arg !== type) {

      console.warn(`You are incorrectly implementing the signature of ${name}. Check param ${idx + 1}`);

    }

  }

}

obj.pickyMethodOne(); 

// > You are incorrectly implementing the signature of pickyMethodOne. Check param 1

// > You are incorrectly implementing the signature of pickyMethodOne. Check param 2

// > You are incorrectly implementing the signature of pickyMethodOne. Check param 3

obj.pickyMethodTwo("wopdopadoo", {}); 

// > You are incorrectly implementing the signature of pickyMethodTwo. Check param 1

// No warnings logged

obj.pickyMethodOne({}, "a little string", 123); 

obj.pickyMethodOne(123, {});

2. 私有屬性

在 JavaScript 或其他語言中,大家會約定俗成地在變量名之前添加下劃線 _ 來表明這是一個私有屬性(并不是真正的私有),但我們無法保證真的沒人會去訪問或修改它。在下面的代碼中,我們聲明了一個私有的 apiKey,便于 api 這個對象內部的方法調用,但不希望從外部也能夠訪問 api._apiKey:

var api = { 

  _apiKey: '123abc456def',

  /* mock methods that use this._apiKey */

  getUsers: function(){}, 

  getUser: function(userId){}, 

  setUser: function(userId, config){}

};

// logs '123abc456def';

console.log("An apiKey we want to keep private", api._apiKey);

// get and mutate _apiKeys as desired

var apiKey = api._apiKey; 

api._apiKey = '987654321';

很顯然,約定俗成是沒有束縛力的。使用 ES6 Proxy 我們就可以實現真實的私有變量了,下面針對不同的讀取方式演示兩個不同的私有化方法。

第一種方法是使用 set / get 攔截讀寫請求并返回 undefined:

let api = { 

  _apiKey: '123abc456def',

  getUsers: function(){ }, 

  getUser: function(userId){ }, 

  setUser: function(userId, config){ }

};

const RESTRICTED = ['_apiKey'];

api = new Proxy(api, { 

  get(target, key, proxy) {

    if(RESTRICTED.indexOf(key) > -1) {

      throw Error(`${key} is restricted. Please see api documentation for further info.`);

    }

    return Reflect.get(target, key, proxy);

  },

  set(target, key, value, proxy) {

    if(RESTRICTED.indexOf(key) > -1) {

      throw Error(`${key} is restricted. Please see api documentation for further info.`);

    }

    return Reflect.get(target, key, value, proxy);

  }

});

// 以下操作都會拋出錯誤

console.log(api._apiKey);

api._apiKey = '987654321';

第二種方法是使用 has 攔截 in 操作:

var api = { 

  _apiKey: '123abc456def',

  getUsers: function(){ }, 

  getUser: function(userId){ }, 

  setUser: function(userId, config){ }

};

const RESTRICTED = ['_apiKey'];

api = new Proxy(api, { 

  has(target, key) {

    return (RESTRICTED.indexOf(key) > -1) ?

      false :

      Reflect.has(target, key);

  }

});

// these log false, and `for in` iterators will ignore _apiKey

console.log("_apiKey" in api);

for (var key in api) { 

  if (api.hasOwnProperty(key) && key === "_apiKey") {

    console.log("This will never be logged because the proxy obscures _apiKey...")

  }

}

3. 訪問日志

對于那些調用頻繁、運行緩慢或占用執行環境資源較多的屬性或接口,開發者會希望記錄它們的使用情況或性能表現,這個時候就可以使用 Proxy 充當中間件的角色,輕而易舉實現日志功能:

let api = { 

  _apiKey: '123abc456def',

  getUsers: function() { /* ... */ },

  getUser: function(userId) { /* ... */ },

  setUser: function(userId, config) { /* ... */ }

};

function logMethodAsync(timestamp, method) { 

  setTimeout(function() {

    console.log(`${timestamp} - Logging ${method} request asynchronously.`);

  }, 0)

}

api = new Proxy(api, { 

  get: function(target, key, proxy) {

    var value = target[key];

    return function(...arguments) {

      logMethodAsync(new Date(), key);

      return Reflect.apply(value, target, arguments);

    };

  }

});

api.getUsers();

4. 預警和攔截

假設你不想讓其他開發者刪除 noDelete 屬性,還想讓調用 oldMethod 的開發者了解到這個方法已經被廢棄了,或者告訴開發者不要修改 doNotChange 屬性,那么就可以使用 Proxy 來實現:

let dataStore = { 

  noDelete: 1235,

  oldMethod: function() {/*...*/ },

  doNotChange: "tried and true"

};

const NODELETE = ['noDelete']; 

const NOCHANGE = ['doNotChange'];

const DEPRECATED = ['oldMethod']; 

dataStore = new Proxy(dataStore, { 

  set(target, key, value, proxy) {

    if (NOCHANGE.includes(key)) {

      throw Error(`Error! ${key} is immutable.`);

    }

    return Reflect.set(target, key, value, proxy);

  },

  deleteProperty(target, key) {

    if (NODELETE.includes(key)) {

      throw Error(`Error! ${key} cannot be deleted.`);

    }

    return Reflect.deleteProperty(target, key);

  },

  get(target, key, proxy) {

    if (DEPRECATED.includes(key)) {

      console.warn(`Warning! ${key} is deprecated.`);

    }

    var val = target[key];

    return typeof val === 'function' ?

      function(...args) {

        Reflect.apply(target[key], target, args);

      } :

      val;

  }

});

// these will throw errors or log warnings, respectively

dataStore.doNotChange = "foo"; 

delete dataStore.noDelete; 

dataStore.oldMethod();

5. 過濾操作

某些操作會非常占用資源,比如傳輸大文件,這個時候如果文件已經在分塊發送了,就不需要在對新的請求作出相應(非絕對),這個時候就可以使用 Proxy 對當請求進行特征檢測,并根據特征過濾出哪些是不需要響應的,哪些是需要響應的。下面的代碼簡單演示了過濾特征的方式,并不是完整代碼,相信大家會理解其中的妙處:

let obj = { 

  getGiantFile: function(fileId) {/*...*/ }

};

obj = new Proxy(obj, { 

  get(target, key, proxy) {

    return function(...args) {

      const id = args[0];

      let isEnroute = checkEnroute(id);

      let isDownloading = checkStatus(id);   

      let cached = getCached(id);

      if (isEnroute || isDownloading) {

        return false;

      }

      if (cached) {

        return cached;

      }

      return Reflect.apply(target[key], target, args);

    }

  }

});

6. 中斷代理

Proxy 支持隨時取消對 target 的代理,這一操作常用于完全封閉對數據或接口的訪問。在下面的示例中,我們使用了 Proxy.revocable 方法創建了可撤銷代理的代理對象:

let sensitiveData = { username: 'devbryce' };

const {sensitiveData, revokeAccess} = Proxy.revocable(sensitiveData, handler);

function handleSuspectedHack(){ 

  revokeAccess();

}

// logs 'devbryce'

console.log(sensitiveData.username);

handleSuspectedHack();

// TypeError: Revoked

console.log(sensitiveData.username);

Decorator

ES7 中實現的 Decorator,相當于設計模式中的裝飾器模式。如果簡單地區分 Proxy 和 Decorator 的使用場景,可以概括為:Proxy 的核心作用是控制外界對被代理者內部的訪問,Decorator 的核心作用是增強被裝飾者的功能。只要在它們核心的使用場景上做好區別,那么像是訪問日志這樣的功能,雖然本文使用了 Proxy 實現,但也可以使用 Decorator 實現,開發者可以根據項目的需求、團隊的規范、自己的偏好自由選擇。

總結

ES6 的 Proxy還是非常實用的,看似簡單的特性,卻有極大的用處。希望給大家學習ES6有所幫助。

更多信息請查看網絡編程
易賢網手機網站地址:詳細探究ES6之Proxy代理
由于各方面情況的不斷調整與變化,易賢網提供的所有考試信息和咨詢回復僅供參考,敬請考生以權威部門公布的正式信息和咨詢為準!

2026上岸·考公考編培訓報班

  • 報班類型
  • 姓名
  • 手機號
  • 驗證碼
關于我們 | 聯系我們 | 人才招聘 | 網站聲明 | 網站幫助 | 非正式的簡要咨詢 | 簡要咨詢須知 | 新媒體/短視頻平臺 | 手機站點 | 投訴建議
工業和信息化部備案號:滇ICP備2023014141號-1 云南省教育廳備案號:云教ICP備0901021 滇公網安備53010202001879號 人力資源服務許可證:(云)人服證字(2023)第0102001523號
云南網警備案專用圖標
聯系電話:0871-65099533/13759567129 獲取招聘考試信息及咨詢關注公眾號:hfpxwx
咨詢QQ:1093837350(9:00—18:00)版權所有:易賢網
云南網警報警專用圖標
中文字幕免费精品_亚洲视频自拍_亚洲综合国产激情另类一区_色综合咪咪久久
亚洲女与黑人做爰| 国产精品乱人伦中文| 国产精品久久久久久久久借妻 | 国产精品久久久一本精品| 亚洲精品一区久久久久久| 老鸭窝亚洲一区二区三区| 欧美日韩一区二区三区在线观看免 | 亚洲一区亚洲| 国产精品亚洲综合一区在线观看| 午夜视频久久久| 亚洲国产成人porn| 欧美日韩精品在线视频| 性欧美1819性猛交| 亚洲精品色婷婷福利天堂| 韩国在线一区| 欧美激情一区二区三区在线视频 | 久久精品视频亚洲| 韩国成人精品a∨在线观看| 欧美国产激情| 欧美一区二区三区精品电影| 亚洲国产成人高清精品| 国产精品久久久久久久久借妻| 久久久久一本一区二区青青蜜月| 日韩午夜激情av| 国产一区二区av| 欧美日韩另类视频| 久久人人97超碰人人澡爱香蕉 | 精品动漫av| 欧美日韩中文精品| 久久夜色撩人精品| 欧美中文字幕第一页| 亚洲欧美不卡| 一本久道久久久| 亚洲国产日韩欧美在线动漫| 国产一区二区三区不卡在线观看| 欧美日韩1区| 麻豆国产va免费精品高清在线| 亚洲午夜电影网| 亚洲美女中文字幕| 在线日韩日本国产亚洲| 国产精品电影在线观看| 欧美理论在线| 欧美成人一二三| 亚洲小视频在线观看| 亚洲国产一区二区三区a毛片| 国产精品伊人日日| 国产精品久久久久国产a级| 欧美日韩国产91| 欧美黄色大片网站| 欧美精品色综合| 欧美成人午夜激情视频| 久久久久久久综合色一本| 久久黄金**| 久久九九热re6这里有精品| 性久久久久久久久久久久| 亚洲欧美日韩在线| 午夜精品视频| 欧美一区二区三区四区在线观看 | 亚洲一二三四久久| 一本久道久久久| 一区二区三区你懂的| 99精品国产福利在线观看免费| 亚洲精品一区在线| 在线亚洲高清视频| 亚洲欧美日本国产有色| 午夜精品久久99蜜桃的功能介绍| 亚洲一区免费看| 欧美在线啊v| 久久午夜av| 欧美精品一区二区高清在线观看| 欧美激情一区二区三区四区| 欧美美女福利视频| 国产精品国产精品| 国产欧美一区二区色老头| 国产亚洲女人久久久久毛片| 影音先锋欧美精品| 99re8这里有精品热视频免费| 这里是久久伊人| 午夜精品在线| 欧美+日本+国产+在线a∨观看| 欧美日本韩国一区二区三区| 欧美特黄a级高清免费大片a级| 国产精品视频99| 伊人男人综合视频网| 久久综合给合久久狠狠色 | 亚洲美女免费精品视频在线观看| 亚洲美女av网站| 亚洲欧美国产毛片在线| 欧美影院精品一区| 欧美一级电影久久| 男男成人高潮片免费网站| 欧美日韩精品在线| 女仆av观看一区| 欧美日韩视频在线第一区| 国产精品免费看| 久久久久久久999| 免费成人性网站| 欧美午夜大胆人体| 国产一区二区精品久久99| 亚洲欧洲精品一区| 欧美一区二区福利在线| 美女任你摸久久| 国产精品久久久久久久久久妞妞 | 久久精品女人天堂| 一区二区日本视频| 国外成人性视频| 欧美日韩伦理在线免费| 日韩网站在线| 久久大逼视频| 欧美精品久久久久久久| 国产日韩欧美中文在线播放| 亚洲盗摄视频| 欧美一区二区日韩一区二区| 欧美精品色综合| 在线成人h网| 欧美一级二级三级蜜桃| 欧美日韩福利| 亚洲高清一区二| 久久久久成人精品| 国产精品视频精品| 在线亚洲激情| 欧美日韩精品在线播放| 亚洲精品久久久一区二区三区| 久久久精品国产免大香伊| 国产精品久久久久久影院8一贰佰| 亚洲精品无人区| 欧美电影在线播放| 影音先锋亚洲视频| 久久亚洲午夜电影| 影音先锋久久| 另类国产ts人妖高潮视频| 韩日视频一区| 久久久中精品2020中文| 欧美亚洲日本国产| 国产精品青草久久| 香蕉久久夜色精品| 国产欧美va欧美va香蕉在| 亚洲尤物视频在线| 国产精品自拍在线| 午夜精品久久久久久久久久久久久| 欧美天天综合网| 亚洲欧美在线一区| 国产精品亚洲第一区在线暖暖韩国| 亚洲制服av| 黄色欧美成人| 女同一区二区| 在线亚洲成人| 亚洲第一免费播放区| 久久永久免费| 欧美日韩一区不卡| 狠狠色狠狠色综合人人| 亚洲大胆av| 激情视频亚洲| 久久久美女艺术照精彩视频福利播放| 国产欧美在线观看| 久久久精品tv| 亚洲欧洲日本在线| 欧美日韩午夜激情| 亚洲在线视频网站| 狠狠色狠狠色综合日日91app| 久久综合九色九九| 亚洲伦理在线观看| 国产精品免费视频xxxx| 久久激情网站| 亚洲黄色在线视频| 欧美体内she精视频| 欧美影院一区| 亚洲电影免费观看高清完整版在线观看 | 久久免费视频在线| 日韩视频精品在线观看| 国产女精品视频网站免费| 看欧美日韩国产| 亚洲少妇一区| 在线日本成人| 国产精品视频福利| 欧美成人一区二区| 香蕉成人啪国产精品视频综合网| 亚洲大片在线观看| 欧美性久久久| 免费观看欧美在线视频的网站| 亚洲视频日本| 亚洲国产高清一区二区三区| 国产精品免费在线| 欧美日本国产一区| 久久一区二区精品| 亚洲欧美日韩一区在线观看| 91久久精品一区二区别| 国产一二三精品| 国产精品视频最多的网站| 欧美日本久久| 免费不卡在线视频| 久久精品日韩一区二区三区| 亚洲一区二区成人| 亚洲精品网址在线观看| 亚洲第一黄色网| 一区二区视频在线观看| 国产日韩综合一区二区性色av| 欧美视频手机在线| 欧美日韩一卡| 欧美日韩一区二区三区四区五区|