詳解ES6中的代理模式——Proxy
什么是代理模式
代理模式(英語(yǔ):Proxy Pattern)是程序設(shè)計(jì)中的一種設(shè)計(jì)模式。
所謂的代理者是指一個(gè)類別可以作為其它東西的接口。代理者可以作任何東西的接口:網(wǎng)絡(luò)連接、內(nèi)存中的大對(duì)象、文件或其它昂貴或無(wú)法復(fù)制的資源。
著名的代理模式例子為引用計(jì)數(shù)(英語(yǔ):reference counting)指針對(duì)象。
當(dāng)一個(gè)復(fù)雜對(duì)象的多份副本須存在時(shí),代理模式可以結(jié)合享元模式以減少內(nèi)存用量。典型作法是創(chuàng)建一個(gè)復(fù)雜對(duì)象及多個(gè)代理者,每個(gè)代理者會(huì)引用到原本的復(fù)雜對(duì)象。而作用在代理者的運(yùn)算會(huì)轉(zhuǎn)送到原本對(duì)象。一旦所有的代理者都不存在時(shí),復(fù)雜對(duì)象會(huì)被移除。
上面是維基百科中對(duì)代理模式的一個(gè)整體的定義.而在JavaScript中代理模式的具體表現(xiàn)形式就是ES6中的新增對(duì)象---Proxy
什么是Proxy對(duì)象
在MDN上對(duì)于 Proxy 的解釋是:
Proxy 對(duì)象用于定義基本操作的自定義行為(如屬性查找,賦值,枚舉,函數(shù)調(diào)用等)。
簡(jiǎn)單來(lái)說(shuō): Proxy 對(duì)象就是可以讓你去對(duì)JavaScript中的一切合法對(duì)象的基本操作進(jìn)行自定義.然后用你自定義的操作去覆蓋其對(duì)象的基本操作.也就是當(dāng)一個(gè)對(duì)象去執(zhí)行一個(gè)基本操作時(shí),其執(zhí)行的過(guò)程和結(jié)果是你自定義的,而不是對(duì)象的.
:sweat:好吧,用文字表達(dá)可能太復(fù)雜了.我們還是直接上代碼吧.
首先Proxy的語(yǔ)法是:
let p = new Proxy(target, handler);
其中:
- target 是你要代理的對(duì)象.它可以是JavaScript中的任何合法對(duì)象.如: (數(shù)組, 對(duì)象, 函數(shù)等等)
- handler 是你要自定義操作方法的一個(gè)集合.
- p 是一個(gè)被代理后的新對(duì)象,它擁有 target 的一切屬性和方法.只不過(guò)其行為和結(jié)果是在 handler 中自定義的.
然后讓我們來(lái)看這段代碼:
let obj = { a: 1, b: 2, } const p = new Proxy(obj, { get(target, key, value) { if (key === 'c') { return '我是自定義的一個(gè)結(jié)果'; } else { return target[key]; } }, set(target, key, value) { if (value === 4) { target[key] = '我是自定義的一個(gè)結(jié)果'; } else { target[key] = value; } } }) console.log(obj.a) // 1 console.log(obj.c) // undefined console.log(p.a) // 1 console.log(p.c) // 我是自定義的一個(gè)結(jié)果 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); // 我是自定義的一個(gè)結(jié)果
從上面這段代碼中,我可以很清楚的看到 Proxy 對(duì)象的作用.即是之前所受的 用于定義基本操作的自定義行為 .同樣的 get 和 set 操作.沒(méi)有沒(méi)代理的對(duì)象所得的結(jié)果是其JavaScript本身的執(zhí)行機(jī)制運(yùn)行計(jì)算后所得到的.而被代理了的對(duì)象的結(jié)果則是我們自定義的.
Proxy所能代理的范圍--handler
在上面代碼中,我們看到了構(gòu)造一個(gè)代理對(duì)象時(shí)所傳的第二個(gè)參數(shù) handler ,這個(gè) handler 對(duì)象是由 get 和 set 兩個(gè)函數(shù)方法組成的.這兩個(gè)方法會(huì)在一個(gè)對(duì)象被 get 和 set 時(shí)被調(diào)用執(zhí)行,以代替原生對(duì)象上的操作.那么為什么在 handler ,定義 get 和 set 這兩個(gè)函數(shù)名之后就代理對(duì)象上的 get 和 set 操作了呢?
實(shí)際上 handler 本身就是ES6所新設(shè)計(jì)的一個(gè)對(duì)象.它的作用就是用來(lái) 自定義代理對(duì)象的各種可代理操作 。它本身一共有13中方法,每種方法都可以代理一種操作.其13種方法如下:
handler.getPrototypeOf() // 在讀取代理對(duì)象的原型時(shí)觸發(fā)該操作,比如在執(zhí)行 Object.getPrototypeOf(proxy) 時(shí)。 handler.setPrototypeOf() // 在設(shè)置代理對(duì)象的原型時(shí)觸發(fā)該操作,比如在執(zhí)行 Object.setPrototypeOf(proxy, null) 時(shí)。 handler.isExtensible() // 在判斷一個(gè)代理對(duì)象是否是可擴(kuò)展時(shí)觸發(fā)該操作,比如在執(zhí)行 Object.isExtensible(proxy) 時(shí)。 handler.preventExtensions() // 在讓一個(gè)代理對(duì)象不可擴(kuò)展時(shí)觸發(fā)該操作,比如在執(zhí)行 Object.preventExtensions(proxy) 時(shí)。 handler.getOwnPropertyDescriptor() // 在獲取代理對(duì)象某個(gè)屬性的屬性描述時(shí)觸發(fā)該操作,比如在執(zhí)行 Object.getOwnPropertyDescriptor(proxy, "foo") 時(shí)。 handler.defineProperty() // 在定義代理對(duì)象某個(gè)屬性時(shí)的屬性描述時(shí)觸發(fā)該操作,比如在執(zhí)行 Object.defineProperty(proxy, "foo", {}) 時(shí)。 handler.has() // 在判斷代理對(duì)象是否擁有某個(gè)屬性時(shí)觸發(fā)該操作,比如在執(zhí)行 "foo" in proxy 時(shí)。 handler.get() // 在讀取代理對(duì)象的某個(gè)屬性時(shí)觸發(fā)該操作,比如在執(zhí)行 proxy.foo 時(shí)。 handler.set() // 在給代理對(duì)象的某個(gè)屬性賦值時(shí)觸發(fā)該操作,比如在執(zhí)行 proxy.foo = 1 時(shí)。 handler.deleteProperty() // 在刪除代理對(duì)象的某個(gè)屬性時(shí)觸發(fā)該操作,比如在執(zhí)行 delete proxy.foo 時(shí)。 handler.ownKeys() // 在獲取代理對(duì)象的所有屬性鍵時(shí)觸發(fā)該操作,比如在執(zhí)行 Object.getOwnPropertyNames(proxy) 時(shí)。 handler.apply() // 在調(diào)用一個(gè)目標(biāo)對(duì)象為函數(shù)的代理對(duì)象時(shí)觸發(fā)該操作,比如在執(zhí)行 proxy() 時(shí)。 handler.construct() // 在給一個(gè)目標(biāo)對(duì)象為構(gòu)造函數(shù)的代理對(duì)象構(gòu)造實(shí)例時(shí)觸發(fā)該操作,比如在執(zhí)行new proxy() 時(shí)。
Proxy的作用
對(duì)于代理模式 Proxy 的作用主要體現(xiàn)在三個(gè)方面:
1、 攔截和監(jiān)視外部對(duì)對(duì)象的訪問(wèn)
2、 降低函數(shù)或類的復(fù)雜度
2、 在復(fù)雜操作前對(duì)操作進(jìn)行校驗(yàn)或?qū)λ栀Y源進(jìn)行管理
而對(duì)于這三個(gè)使用方面的具體表現(xiàn)大家可以參考這篇文章-- 實(shí)例解析ES6 Proxy使用場(chǎng)景
Proxy的兼容性
參考資料:
以上就是本文的全部?jī)?nèi)容,希望對(duì)大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。
- 實(shí)例解析ES6 Proxy使用場(chǎng)景介紹
- ES6中Proxy與Reflect實(shí)現(xiàn)重載(overload)的方法
- 詳細(xì)探究ES6之Proxy代理
- ES6中Proxy代理用法實(shí)例淺析
- 淺談es6語(yǔ)法 (Proxy和Reflect的對(duì)比)
- ES6之Proxy的get方法詳解
- JavaScript中的ES6 Proxy的具體使用
- ES6 Proxy實(shí)現(xiàn)Vue的變化檢測(cè)問(wèn)題
- ES6知識(shí)點(diǎn)整理之Proxy的應(yīng)用實(shí)例詳解
- ES6 proxy和reflect的使用方法與應(yīng)用實(shí)例分析
- ES6中javascript實(shí)現(xiàn)函數(shù)綁定及類的事件綁定功能詳解
- ES6使用新特性Proxy實(shí)現(xiàn)的數(shù)據(jù)綁定功能實(shí)例
相關(guān)文章
javascript 獲取鼠標(biāo)的絕對(duì)位置 event
javascript 獲取鼠標(biāo)的絕對(duì)位置 event2009-06-06關(guān)于function類中定義變量this的簡(jiǎn)單說(shuō)明
下面小編就為大家?guī)?lái)一篇關(guān)于function類中定義變量this的簡(jiǎn)單說(shuō)明。小編覺得挺不錯(cuò)的,現(xiàn)在就分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧2016-05-05一文搞懂TypeScript的安裝、使用、自動(dòng)編譯的教程
TypeScript 是一種由微軟開發(fā)的開源、跨平臺(tái)的編程語(yǔ)言。它是 JavaScript 的超集,最終會(huì)被編譯為 JavaScript 代碼,關(guān)于TypeScript的安裝、使用、自動(dòng)編譯很多朋友不是很清楚,今天抽空給大家普及下,感興趣的朋友一起看看吧2021-06-06js中的escape及unescape函數(shù)的php實(shí)現(xiàn)代碼
js中的escape及unescape函數(shù)的php實(shí)現(xiàn)代碼...2007-09-09javascript動(dòng)態(tài)添加、修改、刪除對(duì)象的屬性與方法詳解
本篇文章主要是對(duì)javascript動(dòng)態(tài)添加、修改、刪除對(duì)象的屬性與方法進(jìn)行了介紹,需要的朋友可以過(guò)來(lái)參考下,希望對(duì)大家有所幫助2014-01-01