Proxy是什么
首先,我們要清楚,Proxy是什么意思,這個(gè)單詞翻譯過來(lái),就是 代理。
可以理解為,有一個(gè)很火的明星,開通了一個(gè)微博賬號(hào),這個(gè)賬號(hào)非常活躍,回復(fù)粉絲、到處點(diǎn)贊之類的,但可能并不是真的由本人在維護(hù)的。
而是在背后有一個(gè)其他人 or 團(tuán)隊(duì)來(lái)運(yùn)營(yíng),我們就可以稱他們?yōu)榇砣耍驗(yàn)樗麄儼l(fā)表的微博就代表了明星本人的意思。
P.S. 強(qiáng)行舉例子,因?yàn)楸救瞬蛔沸牵皇遣聹y(cè)可能會(huì)有這樣的運(yùn)營(yíng)團(tuán)隊(duì)
這個(gè)代入到JavaScript當(dāng)中來(lái),就可以理解為對(duì)對(duì)象或者函數(shù)的代理操作。
JavaScript中的Proxy
Proxy是ES6中提供的新的API,可以用來(lái)定義對(duì)象各種基本操作的自定義行為 (在文檔中被稱為traps,我覺得可以理解為一個(gè)針對(duì)對(duì)象各種行為的鉤子),拿它可以做很多有意思的事情,在我們需要對(duì)一些對(duì)象的行為進(jìn)行控制時(shí)將變得非常有效。
Proxy的語(yǔ)法
創(chuàng)建一個(gè)Proxy的實(shí)例需要傳入兩個(gè)參數(shù)
1.target 要被代理的對(duì)象,可以是一個(gè)object或者function
2.handlers對(duì)該代理對(duì)象的各種操作行為處理
let target = {}let handlers = {} // do nothinglet proxy = new Proxy(target, handlers)proxy.a = 123console.log(target.a) // 123在第二個(gè)參數(shù)為空對(duì)象的情況下,基本可以理解為是對(duì)第一個(gè)參數(shù)做的一次淺拷貝
(Proxy必須是淺拷貝,如果是深拷貝則會(huì)失去了代理的意義)
Traps(各種行為的代理)
就像上邊的示例代碼一樣,如果沒有定義對(duì)應(yīng)的trap,則不會(huì)起任何作用,相當(dāng)于直接操作了target。
當(dāng)我們寫了某個(gè)trap以后,在做對(duì)應(yīng)的動(dòng)作時(shí),就會(huì)觸發(fā)我們的回調(diào)函數(shù),由我們來(lái)控制被代理對(duì)象的行為。
最常用的兩個(gè)trap應(yīng)該就是get和set了。
早年JavaScript有著在定義對(duì)象時(shí)針對(duì)某個(gè)屬性進(jìn)行設(shè)置getter、setter:
let obj = {_age: 18,get age () {return `I'm ${this._age} years old`},set age (val) {this._age = Number(val)}}console.log(obj.age) // I'm 18 years oldobj.age = 19console.log(obj.age) // I'm 19 years old就像這段代碼描述的一樣,我們?cè)O(shè)置了一個(gè)屬性_age,然后又設(shè)置了一個(gè)get age和set age。
然后我們可以直接調(diào)用obj.age來(lái)獲取一個(gè)返回值,也可以對(duì)其進(jìn)行賦值。
這么做有幾個(gè)缺點(diǎn):
1.針對(duì)每一個(gè)要代理的屬性都要編寫對(duì)應(yīng)的getter、setter。
2.必須還要存在一個(gè)存儲(chǔ)真實(shí)值的key(如果我們直接在getter里邊調(diào)用this.age則會(huì)出現(xiàn)堆棧溢出的情況,因?yàn)闊o(wú)論何時(shí)調(diào)用this.age進(jìn)行取值都會(huì)觸發(fā)getter)。
Proxy很好的解決了這兩個(gè)問題:
let target = { age: 18, name: 'Niko Bellic' }let handlers = {get (target, property) {return `${property}: ${target[property]}`},set (target, property, value) {target[property] = value}}let proxy = new Proxy(target, handlers)proxy.age = 19console.log(target.age, proxy.age) // 19, age : 19console.log(target.name, proxy.name) // Niko Bellic, name: Niko Bellic            
新聞熱點(diǎn)
疑難解答
圖片精選