首頁 >web前端 >js教程 >詳細介紹ES6中的代理模式(Proxy)

詳細介紹ES6中的代理模式(Proxy)

亚连
亚连原創
2018-06-13 10:51:122035瀏覽

這篇文章主要介紹了詳解ES6中的代理模式-Proxy,現在分享給大家,也為大家做個參考。

什麼是代理模式

代理模式(英文:Proxy Pattern)是程式設計中的一種設計模式。

所謂的代理者是指一個類別可以作為其它東西的介面。代理程式可以作任何東西的介面:網路連線、記憶體中的大物件、檔案或其它昂貴或無法複製的資源。

著名的代理模式範例為引用計數(英文:reference counting)指針對象。

當一個複雜物件的多份副本必須存在時,代理模式可以結合享元模式以減少記憶體用量。典型作法是創建一個複雜物件及多個代理者,每個代理程式都會引用到原本的複雜物件。而作用在代理者的運算會轉送到原本物件。一旦所有的代理者都不存在時,複雜物件就會被移除。

上面是維基百科中對代理模式的一個整體的定義.而在JavaScript中代理模式的具體表現形式就是ES6中的新增物件---Proxy

什麼是Proxy物件

在MDN上對於Proxy 的解釋是:

Proxy 物件用於定義基本操作的自訂行為(如屬性查找,賦值,枚舉,函數調用等)。

簡單來說: Proxy 物件就是可以讓你去對JavaScript中的一切合法物件的基本操作進行自訂.然後用你自訂的操作去覆寫其物件的基本操作.也就是當一個物件去執行一個基本操作時,其執行的過程和結果是你自訂的,而不是物件的.

:sweat:好吧,用文字表達可能太複雜了.我們還是直接上程式碼吧.

首先Proxy的語法是:

let p = new Proxy(target, handler);

其中:

  1. target 是你要代理的物件.它可以是JavaScript中的任何合法物件.如: (數組, 物件, 函數等等)

  2. handler 是你要自訂運算方法的集合.

  3. p 是一個被代理後的新物件,它擁有target 的一切屬性和方法.只不過其行為和結果是在handler 中自定義的.

然後讓我們來看這段程式碼:

let obj = {
 a: 1,
 b: 2,
}

const p = new Proxy(obj, {
 get(target, key, value) {
  if (key === 'c') {
   return '我是自定义的一个结果';
  } else {
   return target[key];
  }
 },

 set(target, key, value) {
  if (value === 4) {
   target[key] = '我是自定义的一个结果';
  } else {
   target[key] = value;
  }
 }
})
console.log(obj.a) // 1
console.log(obj.c) // undefined
console.log(p.a) // 1
console.log(p.c) // 我是自定义的一个结果
obj.name = '李白';
console.log(obj.name); // 李白
obj.age = 4;
console.log(obj.age); // 4
p.name = '李白';
console.log(p.name); // 李白
p.age = 4;
console.log(p.age); // 我是自定义的一个结果

從上面這段程式碼中,我可以很清楚的看到Proxy 物件的作用.即是之前所受的用於定義基本操作的自訂行為.同樣的get 和set 操作.沒有沒代理的物件所得的結果是其JavaScript本身的執行機制運行計算後所得到的.而被代理了的對象的結果則是我們自定義的.

Proxy所能代理的範圍--handler

在上面程式碼中,我們看到了建構一個代理物件時所傳的第二個參數handler ,這個handler 物件是由get 和set 兩個函數方法組成的.這兩個方法會在一個物件被get 和set 時被呼叫執行,以代替原生物件上的操作.那麼為什麼在handler ,定義get 和set 這兩個函數名之後就代理物件上的get 和set 運算了呢?

實際上handler 本身就是ES6所新設計的一個物件.它的作用就是用來自訂代理物件的各種可代理操作。它本身一共有13中方法,每種方法都可以代理一種操作.其13種方法如下:

handler.getPrototypeOf()

// 在读取代理对象的原型时触发该操作,比如在执行 Object.getPrototypeOf(proxy) 时。

handler.setPrototypeOf()

// 在设置代理对象的原型时触发该操作,比如在执行 Object.setPrototypeOf(proxy, null) 时。

handler.isExtensible()

// 在判断一个代理对象是否是可扩展时触发该操作,比如在执行 Object.isExtensible(proxy) 时。

handler.preventExtensions()

// 在让一个代理对象不可扩展时触发该操作,比如在执行 Object.preventExtensions(proxy) 时。

handler.getOwnPropertyDescriptor()

// 在获取代理对象某个属性的属性描述时触发该操作,比如在执行 Object.getOwnPropertyDescriptor(proxy, "foo") 时。

handler.defineProperty()

// 在定义代理对象某个属性时的属性描述时触发该操作,比如在执行 Object.defineProperty(proxy, "foo", {}) 时。

handler.has()

// 在判断代理对象是否拥有某个属性时触发该操作,比如在执行 "foo" in proxy 时。

handler.get()

// 在读取代理对象的某个属性时触发该操作,比如在执行 proxy.foo 时。

handler.set()

// 在给代理对象的某个属性赋值时触发该操作,比如在执行 proxy.foo = 1 时。

handler.deleteProperty()

// 在删除代理对象的某个属性时触发该操作,比如在执行 delete proxy.foo 时。

handler.ownKeys()

// 在获取代理对象的所有属性键时触发该操作,比如在执行 Object.getOwnPropertyNames(proxy) 时。

handler.apply()

// 在调用一个目标对象为函数的代理对象时触发该操作,比如在执行 proxy() 时。

handler.construct()

// 在给一个目标对象为构造函数的代理对象构造实例时触发该操作,比如在执行new proxy() 时。

Proxy的作用

#對於代理模式Proxy的作用主要體現在三個面向:

1、 攔截和監視外部對物件的存取

#2、降低函數或類別的複雜度

2、 在複雜操作前對操作進行校驗或對所需資源進行管理

而對於這三個使用方面的具體表現大家可以參考這篇文章-- 實例解析ES6 Proxy使用場景

# Proxy的兼容性

參考資料:

#MDN---Proxy

##實例解析ES6 Proxy使用場景

上面是我整理給大家的,希望未來會對大家有幫助。

相關文章:

在VueJs中如何監聽window.resize具體該怎麼實現?

在AngularJS中有關監聽ng-repeat渲染問題

在VUE移動音樂WEBAPP中有關跨域請求失敗方面的問題

以上是詳細介紹ES6中的代理模式(Proxy)的詳細內容。更多資訊請關注PHP中文網其他相關文章!

陳述:
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn