JavaScript使用Proxy編寫(xiě)一個(gè)取值限制器
前言
最近一直在開(kāi)發(fā)低代碼平臺(tái)的東西,由于項(xiàng)目里面東西有點(diǎn)多,取值或調(diào)用起來(lái)比較麻煩,特別是那些實(shí)例的特殊函數(shù)和變量。
所以我實(shí)現(xiàn)了一個(gè)實(shí)例收集器,讓開(kāi)發(fā)者的權(quán)限變得非常高,細(xì)節(jié)就不聊了。
盡管這樣子會(huì)讓開(kāi)發(fā)的體驗(yàn)變得很簡(jiǎn)單,但是大家都知道最便宜的東西往往是最昂貴的,當(dāng)你可以隨意在項(xiàng)目中讀取到不同組件的實(shí)例的時(shí)候,很容易導(dǎo)致某一個(gè)組件和另一個(gè)風(fēng)馬牛不相及的組件產(chǎn)生關(guān)聯(lián),當(dāng)某一側(cè)不當(dāng)操作修了實(shí)例的某些內(nèi)容的話,很可能導(dǎo)致隱藏且嚴(yán)重的bug。
因此對(duì)于這種上帝的操作 必須進(jìn)行限制,因此對(duì)此我創(chuàng)建了一個(gè)取值限制器來(lái)進(jìn)行約束,代碼很簡(jiǎn)單,不妨一看。
源碼實(shí)現(xiàn)
// 初始化 限制proxy生成函數(shù) 的 構(gòu)造函數(shù)
// fn 校驗(yàn)當(dāng)前對(duì)象是否可以讀取
const LimitProxyConstructorFn = (fn) => {
// 限制proxy
// target 需要劫持的對(duì)象
const createLimitProxy = (target) => {
return new Proxy(target, {
get(target, property) {
const res = Reflect.get(target, property);
const isLegal = fn(property);
// 判斷當(dāng)前取值是否是對(duì)象,因?yàn)閷?duì)象可能要限制取值
if (typeof res === "object" && res !== null) {
// 合法對(duì)象 返回一個(gè)禁止賦值但支持取值的proxy對(duì)象
if (isLegal) {
return new Proxy(target, {
get(target, property) {
return Reflect.get(target, property);
},
set() {
throw new Error("無(wú)法寫(xiě)入屬性");
},
});
}
// 如果不合法,則遞歸創(chuàng)建 限制proxy
return createLimitProxy(res);
} else {
// 如果當(dāng)前項(xiàng)不是對(duì)象,判斷是否合法,合法則返回,反之異常
if (isLegal) return res;
throw new Error("取值不合法");
}
},
set() {
throw new Error("無(wú)法寫(xiě)入屬性");
},
});
};
return createLimitProxy;
};
測(cè)試用例
初始化限制proxy對(duì)象構(gòu)造函數(shù)

效果如下:

limitProxy 是一個(gè)proxy代理對(duì)象
看到藍(lán)色框里面的是取值操作,只有以__開(kāi)頭的屬性才能讀取。

如果__ 開(kāi)頭的屬性是一個(gè)對(duì)象則,該對(duì)象下所有的屬性都可以讀取。

反之認(rèn)為讀取不合法。

可以看到紅框里面都是賦值操作,限制proxy禁用了所有的賦值操作,保證原數(shù)據(jù)的安全

代碼解釋
這段代碼的作用是創(chuàng)建一個(gè)可以限制對(duì)象屬性讀取和寫(xiě)入操作的代理對(duì)象生成函數(shù)。傳入的驗(yàn)證函數(shù) fn 用于確定哪些屬性是合法的。
生成的代理對(duì)象會(huì)根據(jù)驗(yàn)證函數(shù)的結(jié)果,限制對(duì)屬性的讀取和寫(xiě)入操作。
代碼解釋:
- 代碼定義了一個(gè)限制proxy函數(shù)的生成函數(shù)
LimitProxyConstructorFn,該函數(shù)接受一個(gè)參數(shù)fn,用于驗(yàn)證當(dāng)前對(duì)象是否可以讀取,fn接受一個(gè)一個(gè)參數(shù)property,即當(dāng)前讀取的對(duì)象的key的名稱,需要返回boolean判斷是否合法。 - 函數(shù)內(nèi)部定義了一個(gè)名為
createLimitProxy的函數(shù),它接受一個(gè)參數(shù)target,表示需要劫持的對(duì)象。createLimitProxy函數(shù)使用new Proxy()創(chuàng)建一個(gè)代理對(duì)象來(lái)限制目標(biāo)對(duì)象的操作。
代理對(duì)象的 get 處理邏輯如下:
使用 Reflect.get() 獲取原始對(duì)象 target 的屬性值,并將結(jié)果存儲(chǔ)在變量 res 中。
調(diào)用驗(yàn)證函數(shù) fn 并傳入屬性名稱 property,將結(jié)果存儲(chǔ)在變量 isLegal 中,用于判斷屬性是否合法。
如果取值 res 是對(duì)象(不包括 null),則進(jìn)行進(jìn)一步處理:
- 如果對(duì)象合法(
isLegal為true),則返回一個(gè)新的代理對(duì)象,該對(duì)象禁止賦值但允許取值。這個(gè)新代理對(duì)象的get處理邏輯與原始代理對(duì)象相同,即返回原始對(duì)象的屬性值,而set處理邏輯拋出一個(gè)錯(cuò)誤,表示無(wú)法寫(xiě)入屬性。 - 如果對(duì)象不合法,則遞歸調(diào)用
createLimitProxy函數(shù),創(chuàng)建針對(duì)該對(duì)象的限制代理,并返回限制代理對(duì)象。
如果取值 res 不是對(duì)象,則判斷屬性是否合法:
- 如果屬性合法,則直接返回取值
res。 - 如果屬性不合法,則拋出一個(gè)錯(cuò)誤,表示取值不合法。
代理對(duì)象的 set 處理邏輯與上述相同,無(wú)論是對(duì)原始對(duì)象還是對(duì)代理對(duì)象進(jìn)行屬性賦值操作,都會(huì)拋出一個(gè)錯(cuò)誤,表示無(wú)法寫(xiě)入屬性。
構(gòu)造函數(shù) LimitProxyConstructorFn 返回內(nèi)部定義的 createLimitProxy 函數(shù),以便可以使用該函數(shù)來(lái)生成限制代理對(duì)象。
總結(jié)
總的來(lái)說(shuō)這個(gè)東西還挺有意思的,特別是那種需要限制取值權(quán)限的場(chǎng)景,代碼也很少,感興趣的朋友不妨了解一下,當(dāng)然代碼還有不少優(yōu)化空間。
到此這篇關(guān)于JavaScript使用Proxy編寫(xiě)一個(gè)取值限制器的文章就介紹到這了,更多相關(guān)JavaScript Proxy取值限制器內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
JavaScript下一版本標(biāo)準(zhǔn)ES6的Set集合使用詳解
ES6:全稱ECMAScript 6.0,是JavaScript語(yǔ)言的國(guó)際標(biāo)準(zhǔn),JavaScript是ECMAScript的實(shí)現(xiàn)。今天我們就來(lái)學(xué)習(xí)一下ES6的Set集合的使用2023-02-02
在ASP.NET MVC項(xiàng)目中使用RequireJS庫(kù)的用法示例
這篇文章主要介紹了在ASP.NET MVC項(xiàng)目中使用RequireJS的用法示例,文中主要講解了網(wǎng)站項(xiàng)目的一些基本目錄結(jié)構(gòu)思想,并給出了一個(gè)半自動(dòng)壓縮的例子,的朋友可以參考下2016-02-02
在Web前端實(shí)現(xiàn)流式TTS播放的排坑過(guò)程
在前端實(shí)現(xiàn)流式TTS,核心目標(biāo)是把文本輸入轉(zhuǎn)化為沉浸式的、幾乎無(wú)感延遲的音頻輸出,并且在音頻進(jìn)入瀏覽器的瞬間就能開(kāi)始播放,這篇文章主要介紹了在Web前端實(shí)現(xiàn)流式TTS播放的排坑過(guò)程,需要的朋友可以參考下2026-05-05
JavaScript設(shè)計(jì)模式中的橋接和中介者模式
這篇文章主要介紹了JavaScript設(shè)計(jì)模式中的橋接和中介者模式,橋接設(shè)計(jì)模式是一種偏向于組合的設(shè)計(jì)模式,而非繼承的設(shè)計(jì)模式,實(shí)現(xiàn)的細(xì)節(jié)從一個(gè)模塊推送給另一個(gè)具有單獨(dú)模塊的對(duì)象,而中介者設(shè)計(jì)模式是指通過(guò)一個(gè)中介者對(duì)象封裝一系列的對(duì)象交互2022-06-06
用JavaScript實(shí)現(xiàn)簡(jiǎn)單網(wǎng)頁(yè)時(shí)鐘
這篇文章主要為大家詳細(xì)介紹了用JavaScript實(shí)現(xiàn)簡(jiǎn)單網(wǎng)頁(yè)時(shí)鐘,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2021-08-08
利用10行js代碼實(shí)現(xiàn)上下滾動(dòng)公告效果
這篇文章主要給大家介紹了關(guān)于利用10行js代碼實(shí)現(xiàn)滾動(dòng)公告效果的相關(guān)資料,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起看看吧。2017-12-12
JavaScript中call和apply方法的區(qū)別實(shí)例分析
這篇文章主要介紹了JavaScript中call和apply方法的區(qū)別,結(jié)合實(shí)例形式分析call和apply方法的功能、原理及相關(guān)使用操作區(qū)別,需要的朋友可以參考下2018-08-08
JavaScript的DOM與BOM的區(qū)別與用法詳解
這篇文章主要為大家詳細(xì)介紹了JavaScript的DOM與BOM的區(qū)別與用法,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下,希望能夠給你帶來(lái)幫助2022-03-03
Typescript 實(shí)現(xiàn)函數(shù)重載的方式
函數(shù)重載簡(jiǎn)單點(diǎn)說(shuō)就是,同一個(gè)函數(shù)的不同實(shí)現(xiàn)方式,根據(jù)傳入的參數(shù)的類(lèi)型或者長(zhǎng)度,決定最終調(diào)用哪一個(gè)實(shí)現(xiàn),本文給大家介紹了Typescript 實(shí)現(xiàn)函數(shù)重載的方式,需要的朋友可以參考下2024-05-05

