這篇文章主要介紹了詳解ES6中的代理模式-Proxy,現在分享給大家,也為大家做個參考。
代理模式(英文:Proxy Pattern)是程式設計中的一種設計模式。
所謂的代理者是指一個類別可以作為其它東西的介面。代理程式可以作任何東西的介面:網路連線、記憶體中的大物件、檔案或其它昂貴或無法複製的資源。
著名的代理模式範例為引用計數(英文:reference counting)指針對象。
當一個複雜物件的多份副本必須存在時,代理模式可以結合享元模式以減少記憶體用量。典型作法是創建一個複雜物件及多個代理者,每個代理程式都會引用到原本的複雜物件。而作用在代理者的運算會轉送到原本物件。一旦所有的代理者都不存在時,複雜物件就會被移除。
上面是維基百科中對代理模式的一個整體的定義.而在JavaScript中代理模式的具體表現形式就是ES6中的新增物件---Proxy
在MDN上對於Proxy 的解釋是:
Proxy 物件用於定義基本操作的自訂行為(如屬性查找,賦值,枚舉,函數調用等)。
簡單來說: Proxy 物件就是可以讓你去對JavaScript中的一切合法物件的基本操作進行自訂.然後用你自訂的操作去覆寫其物件的基本操作.也就是當一個物件去執行一個基本操作時,其執行的過程和結果是你自訂的,而不是物件的.
:sweat:好吧,用文字表達可能太複雜了.我們還是直接上程式碼吧.
首先Proxy的語法是:
let p = new Proxy(target, handler);
其中:
target 是你要代理的物件.它可以是JavaScript中的任何合法物件.如: (數組, 物件, 函數等等)
handler 是你要自訂運算方法的集合.
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本身的執行機制運行計算後所得到的.而被代理了的對象的結果則是我們自定義的.
在上面程式碼中,我們看到了建構一個代理物件時所傳的第二個參數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使用場景
參考資料:
#MDN---Proxy
##實例解析ES6 Proxy使用場景上面是我整理給大家的,希望未來會對大家有幫助。 相關文章:在VueJs中如何監聽window.resize具體該怎麼實現?
以上是詳細介紹ES6中的代理模式(Proxy)的詳細內容。更多資訊請關注PHP中文網其他相關文章!