js對(duì)象屬性的攔截與Proxy代理與Reflect映射的用法和區(qū)別講解
對(duì)象屬性的攔截
介紹
在對(duì)象中,set 和 get 是屬性的特性,用于定義屬性的賦值和取值行為。它們?cè)试S您在屬性被賦值或取值時(shí)執(zhí)行自定義的邏輯。
Set
set 是一個(gè)對(duì)象屬性的特性,用于定義屬性的賦值行為。當(dāng)給屬性賦值時(shí),set 方法會(huì)被調(diào)用,允許執(zhí)行自定義的邏輯。
let obj = { name:0, set changename(value){ if (value >5) { this.name =value; } } } obj.changename=10 //10 obj.changename=4 //0 console.log(obj.name);
通過(guò)changename函數(shù) 在里面進(jìn)行需要的條件判斷來(lái)修改name值,給這個(gè)函數(shù)賦值的時(shí)候,就會(huì)觸發(fā)這個(gè)set。
注意 函數(shù)名跟屬性名不能一樣,不然就要遞歸調(diào)用報(bào)棧溢出錯(cuò)誤了
Get
get 用于定義對(duì)象屬性的獲取行為。當(dāng)訪問(wèn)對(duì)象的屬性時(shí),get 方法會(huì)被觸發(fā),并且可以在方法中執(zhí)行相應(yīng)的邏輯。
let obj = { name:0, set changename(value){ if (value >5) { this.name =value; } }, get changename(){ return this.name =1 }, } obj.changename=10 //10 obj.changename=4 //0 console.log(obj.changename); //1 (獲取的時(shí)候會(huì)觸發(fā)get)
假設(shè) 我們要訪問(wèn)一個(gè)屬性,然后不管設(shè)置還有獲取都需要對(duì)這個(gè)屬性進(jìn)行相應(yīng)操作 ,我們就可以使用 很好的搭配使用set和get。 其實(shí)就相當(dāng)于你針對(duì)一個(gè)屬性寫了兩個(gè)不同的函數(shù)進(jìn)行操作,只不過(guò) set get 我們寫的函數(shù)名稱一樣,便于易讀瀏覽。
對(duì)象的攔截
介紹
Proxy 是 JavaScript 提供的一個(gè)內(nèi)置對(duì)象,用于創(chuàng)建一個(gè)代理對(duì)象,可以攔截并自定義對(duì)目標(biāo)對(duì)象的操作。通過(guò)使用 Proxy,我們可以對(duì)目標(biāo)對(duì)象的屬性訪問(wèn)、賦值、刪除等操作進(jìn)行攔截和處理。
使用
let obj = { name: 0, }; let handle = { set: function (target, name, value) { if (value > 5) { target[name] = value; } }, get: function (target, name) { return (target[name] = 1); }, }; let proxy = new Proxy(obj, handle); proxy.changename = 10; //10 proxy.changename = 4; //0 console.log(proxy.changename); //1
通過(guò)proxy代理來(lái)訪問(wèn) 對(duì)象進(jìn)行獲取和賦值等操作。
對(duì)象屬性攔截和對(duì)象攔截區(qū)別
區(qū)別就跟名字一樣,對(duì)象屬性攔截,是你在對(duì)象中給某個(gè)屬性設(shè)置攔截操作,當(dāng)它獲取,和賦值的時(shí)候觸發(fā),對(duì)象攔截 是設(shè)置proxy代理,通過(guò)代理來(lái)訪問(wèn),既然通過(guò)代理來(lái)訪問(wèn)對(duì)象屬性,則任何操作,只要你對(duì)這個(gè)對(duì)象有操作,都會(huì)進(jìn)行攔截判斷,
也就是說(shuō) 一個(gè)是針對(duì)對(duì)象里的一個(gè)屬性,一個(gè)是針對(duì)整個(gè)對(duì)象。
練習(xí)題
let obj = { name: 0, set changename(value) { if (value > 5) { this.name = value; } }, get changename() { return (this.name += 1); }, }; let handle = { //target原對(duì)象,name是屬性 get: function (target, name) { target[name] += 1; //注意 get 一定要return return target[name]; }, //value傳的值 set: function (target, name, value) { if (typeof value == "number") { target[name] = value; } }, }; let proxy = new Proxy(obj, handle); proxy.changename = 10; proxy.changename = "4"; console.log(proxy.changename);
寫了個(gè)題目 供大家練習(xí),感覺有面試題那味兒了,大家看看自己得出的結(jié)果是多少。
揭曉答案: 13。
講解:proxy.changename = 10; 走proxy里的set, set里進(jìn)行判斷是一個(gè)數(shù)值,然后調(diào)用obj對(duì)象進(jìn)行賦值,賦值的時(shí)候會(huì)觸發(fā)obj的set攔截,判斷大于5,ok最后賦值成10.
第二次 賦值字符串4 set判斷 不通過(guò)就沒(méi)下文了,默認(rèn)return 一個(gè)undefined。
然后就是最后的顯示了,顯示的時(shí)候會(huì)觸發(fā)proxy里的get 然后執(zhí)行這段代碼
target[name] += 1;
也就是
target[name] =target[name] +1;
target[name] +1里的target[name] ,就相當(dāng)于get操作觸發(fā)obj里的get,于是就會(huì)加一,10+1變成了11,然后是11加1。也就是十二。
然后return target[name]; 又試一次get 操作 就是12 +1 結(jié)果就變成了 13。
映射
介紹
Reflect 是一個(gè)內(nèi)置的 JavaScript 對(duì)象,它提供了一組用于操作對(duì)象的方法。這些方法與對(duì)象的操作行為相對(duì)應(yīng),例如屬性訪問(wèn)、函數(shù)調(diào)用、實(shí)例化等。
通俗來(lái)講,我們可以使用這個(gè)對(duì)象,來(lái)進(jìn)行日常的對(duì)象操作,比如取值,賦值等等一些操作,他同樣可以完成并且有一些其他的優(yōu)點(diǎn),我們使用reflect一般都是搭配proxy使用。
比如像下面這樣。
const obj = { foo: 42, }; const value = Reflect.get(obj, 'foo'); console.log(value); // 輸出: 42
優(yōu)點(diǎn)
- 方便處理和調(diào)用目標(biāo)對(duì)象的默認(rèn)行為:Reflect 提供了與目標(biāo)對(duì)象的默認(rèn)行為相對(duì)應(yīng)的方法,比如 Reflect.get、Reflect.set、Reflect.has 等。在 Proxy 的處理程序中使用 Reflect 可以方便地調(diào)用這些方法,從而實(shí)現(xiàn)對(duì)目標(biāo)對(duì)象默認(rèn)行為的處理和攔截。
- 更嚴(yán)謹(jǐn)?shù)腻e(cuò)誤處理:Reflect 方法的返回值會(huì)更加準(zhǔn)確地反映操作的結(jié)果,而不是像在使用目標(biāo)對(duì)象的方法時(shí)可能會(huì)拋出異常。例如,Reflect.set 方法在賦值操作成功時(shí)會(huì)返回 true,失敗時(shí)會(huì)返回 false,而不是拋出異常。
- 保持 Proxy 和目標(biāo)對(duì)象的行為一致:Proxy 的目標(biāo)對(duì)象可能是任意類型的對(duì)象,而 Reflect 提供了一致的方法,可以在 Proxy 的處理程序中對(duì)不同類型的目標(biāo)對(duì)象進(jìn)行操作,保持行為的一致性。
- 更清晰的代碼邏輯:使用 Reflect 方法可以使代碼更加簡(jiǎn)潔和易讀,因?yàn)?Reflect 方法的命名和用法更加一致和直觀,能夠更清晰地表達(dá)代碼的意圖。
把它應(yīng)用到我們上面的題。
let obj = { name: 0, set changename(value) { if (value > 5) { this.name = value; } }, get changename() { return (this.name += 1); }, }; let handle = { //target原對(duì)象,name是屬性 get: function (target, name) { target[name] += 1; //注意 get 一定要return return Reflect.get(target, name); }, //value傳的值 set: function (target, name, value) { if (typeof value == "number") { Reflect.set(target, name, value) } }, }; let proxy = new Proxy(obj, handle); proxy.changename = 10; proxy.changename = "4"; console.log(proxy.changename); ···
總結(jié)
對(duì)象屬性的攔截(Object Property Interception):可以使用對(duì)象自身的 get 和 set 方法來(lái)攔截屬性的獲取和設(shè)置操作。通過(guò)在對(duì)象上定義這些方法,可以在屬性訪問(wèn)過(guò)程中執(zhí)行自定義的邏輯,例如驗(yàn)證、轉(zhuǎn)換或攔截。
代理對(duì)象(Proxy Object):代理對(duì)象是一個(gè)代理目標(biāo)對(duì)象的對(duì)象,通過(guò)代理對(duì)象可以攔截對(duì)目標(biāo)對(duì)象的操作。代理對(duì)象使用 Proxy 構(gòu)造函數(shù)創(chuàng)建,并提供了一組攔截器(handler)來(lái)定義攔截行為。
Reflect 映射(Reflect Mapping):Reflect 是一個(gè)內(nèi)置的對(duì)象,提供了一組與對(duì)象操作相關(guān)的方法,用于執(zhí)行與目標(biāo)對(duì)象相同的操作。Reflect 方法提供了一種更簡(jiǎn)潔、易讀的方式來(lái)執(zhí)行常見的對(duì)象操作,如獲取屬性值、設(shè)置屬性值、調(diào)用函數(shù)等。
到此這篇關(guān)于js對(duì)象屬性的攔截與Proxy代理與Reflect映射的用法和區(qū)別講解的文章就介紹到這了,更多相關(guān)js對(duì)象屬性攔截內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
javascript代碼運(yùn)行不出來(lái)執(zhí)行錯(cuò)誤的可能情況整理
js代碼運(yùn)行不出來(lái)的情況在項(xiàng)目中經(jīng)常發(fā)生,究竟是什么原因呢?在本文整理了一些常見的情況,感興趣的各位朋友可以參考下2013-10-10javascript 秒表計(jì)時(shí)器實(shí)現(xiàn)代碼
這篇文章主要介紹了javascript 秒表計(jì)時(shí)器實(shí)現(xiàn)代碼的相關(guān)資料,需要的朋友可以參考下2017-03-03