JS使用位運(yùn)算實(shí)現(xiàn)權(quán)限組合的代碼示例
在業(yè)務(wù)開發(fā)中我們經(jīng)常會(huì)遇到處理不同權(quán)限的情況,例如根據(jù)用戶角色是否有編輯權(quán)限來展示和隱藏一個(gè)按鈕,或者一個(gè)函數(shù)根據(jù)傳入的配置項(xiàng)來執(zhí)行不同的邏輯,也就是所謂的權(quán)限控制。
在判斷用戶是否擁有某個(gè)權(quán)限時(shí),一般情況下我們會(huì)這樣寫:
// 用戶信息
const userInfo = {
permission: 1
};
const READ = 0; // 讀取權(quán)限
const WRITE = 1; // 寫入權(quán)限
const DELETE = 1; // 刪除權(quán)限
// 判斷用戶是否有刪除權(quán)限
if(userInfo.perssion === DELETE) {
// do something...
}
但如果要判斷是否同時(shí)擁有讀取和刪除權(quán)限時(shí),上面這種方法就做不到了,因?yàn)橹荒芘袛嘁环N權(quán)限。在多于一種權(quán)限的組合狀態(tài)下,就需要用到位運(yùn)算了。
例如在Loash的baseClone方法里,使用了bitmask參數(shù)來判斷是否深度克隆,是否克隆symbols等。


普通的克隆方法clone和深度克隆方法cloneDeep基于baseClone封裝而來,兩者的區(qū)別是在第二個(gè)參數(shù)的值有區(qū)別,這里就是運(yùn)用了位運(yùn)算。


接下來讓我們一起研究下這個(gè)位運(yùn)算是個(gè)什么東西。
1、位運(yùn)算概述
現(xiàn)代計(jì)算機(jī)中所有的數(shù)據(jù)是以二進(jìn)制的形式存儲(chǔ)在設(shè)備中的。即 0、1 兩種狀態(tài),計(jì)算機(jī)對(duì)二進(jìn)制數(shù)據(jù)進(jìn)行的運(yùn)算(+、-、*、/)都是叫位運(yùn)算。
2、位運(yùn)算符概覽
| 符號(hào) | 描述 | 運(yùn)算規(guī)則 |
|---|---|---|
| & | 與 | 兩個(gè)位都為1時(shí),結(jié)果才為1 |
| | | 或 | 兩個(gè)位都為0時(shí),結(jié)果才為0 |
| 異或 | 兩個(gè)位相同為0,相異為1 | |
| ~ | 取反 | 0變1,1變0 |
| << | 左移 | 各二進(jìn)位全部左移若干位,高位丟棄,低位補(bǔ)0 |
| >> | 右移 | 各二進(jìn)位全部右移若干位,對(duì)無符號(hào)數(shù),高位補(bǔ)0,有符號(hào)數(shù),各編譯器處理方法不一樣,有的補(bǔ)符號(hào)位(算術(shù)右移),有的補(bǔ)0(邏輯右移) |
3、位運(yùn)算實(shí)現(xiàn)權(quán)限組合
既然位運(yùn)算是以二進(jìn)制數(shù)據(jù)做運(yùn)算,因此我們可以用二進(jìn)制數(shù)定義權(quán)限變量。
const READ = 0b0001; // 讀取權(quán)限 const WRITE = 0b0010; // 寫入權(quán)限 const DELETE = 0b0100; // 刪除權(quán)限 // 或 const READ = 1; const WRITE = 2; const DELETE = 4;
1)權(quán)限組合(添加權(quán)限)
上面已經(jīng)定義了讀、寫、刪三個(gè)單獨(dú)權(quán)限。如果要定義一個(gè)讀寫權(quán)限,需要怎么定義呢。
根據(jù)|運(yùn)算符的規(guī)則可知,當(dāng)兩個(gè)位中只要有一個(gè)為1,結(jié)果為1。因此可以這樣定義讀寫權(quán)限:
const READ = 0b0001; // 讀取權(quán)限 const WRITE = 0b0010; // 寫入權(quán)限 // 組合讀寫權(quán)限 const READ_WRITE = READ | WRITE; // 0b0011
2)權(quán)限切換
當(dāng)用戶擁有讀權(quán)限,就刪除用戶的讀權(quán)限;當(dāng)用戶沒有讀權(quán)限,就添加讀權(quán)限。這樣的權(quán)限切換,要怎么實(shí)現(xiàn)呢。
根據(jù)^運(yùn)算符規(guī)則可知,當(dāng)兩個(gè)位相同時(shí)為0,相異為1。
// 當(dāng)兩個(gè)值相等時(shí),結(jié)果為0。即自己與自己做異或運(yùn)算時(shí),結(jié)果為0。 0b0001 ^ 0b0001 // 0b0000 // 一個(gè)0值與目標(biāo)做異或運(yùn)算時(shí),得到目標(biāo)值。 0b0000 ^ 0b0001 // 0b0001
因此,要切換哪個(gè)權(quán)限,只需要與該權(quán)限做異或運(yùn)算就可以了。
const READ = 0b0001; // 讀取權(quán)限 const WRITE = 0b0010; // 寫入權(quán)限 // 用戶權(quán)限 let userPermission = READ | WRITE; // 0b0011 讀寫權(quán)限 // 切換讀取權(quán)限 userPermission = userPermission ^ READ; // 0b0010 第一次執(zhí)行,刪除讀權(quán)限 userPermission = userPermission ^ READ; // 0b0011 第二次執(zhí)行,添加讀權(quán)限
3)判斷權(quán)限組合中是否擁有某個(gè)權(quán)限
當(dāng)用戶擁有一個(gè)權(quán)限組合,怎么判斷用戶是否擁有某個(gè)權(quán)限呢。
根據(jù)&運(yùn)算符規(guī)則可知,當(dāng)兩個(gè)位都為1時(shí)結(jié)果為1,否則結(jié)果為0。
// 自己與自己做與運(yùn)算時(shí),結(jié)果為自己。 0b0001 & 0b0001 // 0b0001 // 一個(gè)0值與目標(biāo)做與運(yùn)算時(shí),結(jié)果為0。 0b0000 & 0b0001 // 0b0000
因此,要判斷是否擁有某個(gè)權(quán)限,只需要與該權(quán)限做與運(yùn)算,與運(yùn)算結(jié)果為該權(quán)限的值則代表擁有該權(quán)限。
const READ = 0b0001; // 讀取權(quán)限 const WRITE = 0b0010; // 寫入權(quán)限 // 用戶權(quán)限 const userPermission = READ | WRITE; // 0b0011 // 判斷是否有讀權(quán)限 const hasReadPermission = (userPermission & READ) === READ; // true
4)刪除權(quán)限組合中的某個(gè)權(quán)限
如果用戶擁有讀寫權(quán)限,想要?jiǎng)h掉用戶的讀權(quán)限,需要怎樣實(shí)現(xiàn)呢。
由以上可知,需要先判讀是否有讀權(quán)限,有的話就做異或運(yùn)算切換(刪除)該權(quán)限。
const READ = 0b0001; // 讀取權(quán)限
const WRITE = 0b0010; // 寫入權(quán)限
// 用戶權(quán)限
const userPermission = READ | WRITE; // 0b0011
const hasPermission = (userPermission, value) => {
return (userPermission & value) === value;
};
// 刪除讀權(quán)限
if(hasPermission(userPermission, READ)) {
userPermission = userPermission ^ READ;
};
以上就是JS使用位運(yùn)算實(shí)現(xiàn)權(quán)限組合的代碼示例的詳細(xì)內(nèi)容,更多關(guān)于JS位運(yùn)算實(shí)現(xiàn)權(quán)限組合的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
js實(shí)現(xiàn)瀏覽本地文件并顯示擴(kuò)展名的方法
這篇文章主要介紹了js實(shí)現(xiàn)瀏覽本地文件并顯示擴(kuò)展名的方法,涉及javascript文件上傳及字符串操作的相關(guān)技巧,非常簡(jiǎn)單實(shí)用,需要的朋友可以參考下2015-08-08
layer彈窗在鍵盤按回車將反復(fù)刷新的實(shí)現(xiàn)方法
今天小編就為大家分享一篇layer彈窗在鍵盤按回車將反復(fù)刷新的實(shí)現(xiàn)方法,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過來看看吧2019-09-09
用JavaScript實(shí)現(xiàn)瀏覽器截圖功能的全過程
在Web開發(fā)中實(shí)現(xiàn)網(wǎng)頁截圖功能可以幫助我們保存網(wǎng)頁內(nèi)容、生成海報(bào)、制作截圖分享等,這篇文章主要介紹了用JavaScript實(shí)現(xiàn)瀏覽器截圖功能的相關(guān)資料,文中通過代碼介紹的非常詳細(xì),需要的朋友可以參考下2025-07-07
js操作XML文件的實(shí)現(xiàn)方法兼容IE與FireFox
下面小編就為大家?guī)硪黄猨s操作XML文件的實(shí)現(xiàn)方法兼容IE與FireFox。小編覺得挺不錯(cuò)的,現(xiàn)在就分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧2016-06-06
原生JS實(shí)現(xiàn)各種運(yùn)動(dòng)之勻速運(yùn)動(dòng)
這篇文章主要為大家詳細(xì)介紹了原生JS實(shí)現(xiàn)各種運(yùn)動(dòng)之勻速運(yùn)動(dòng),文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2021-08-08
javascript中的后退和刷新實(shí)現(xiàn)方法
下面小編就為大家?guī)硪黄猨avascript中的后退和刷新實(shí)現(xiàn)方法。小編覺得挺不錯(cuò)的,現(xiàn)在就分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧2016-11-11
使用ngrok+express解決本地環(huán)境中微信接口調(diào)試問題
這篇文章主要介紹了使用ngrok+express解決本地環(huán)境中微信接口調(diào)試問題,需要的朋友可以參考下2018-02-02

