JS使用位運算實現(xiàn)權(quán)限組合的代碼示例
在業(yè)務開發(fā)中我們經(jīng)常會遇到處理不同權(quán)限的情況,例如根據(jù)用戶角色是否有編輯權(quán)限來展示和隱藏一個按鈕,或者一個函數(shù)根據(jù)傳入的配置項來執(zhí)行不同的邏輯,也就是所謂的權(quán)限控制。
在判斷用戶是否擁有某個權(quán)限時,一般情況下我們會這樣寫:
// 用戶信息 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... }
但如果要判斷是否同時擁有讀取和刪除權(quán)限時,上面這種方法就做不到了,因為只能判斷一種權(quán)限。在多于一種權(quán)限的組合狀態(tài)下,就需要用到位運算了。
例如在Loash
的baseClone
方法里,使用了bitmask
參數(shù)來判斷是否深度克隆,是否克隆symbols等。
普通的克隆方法clone
和深度克隆方法cloneDeep
基于baseClone
封裝而來,兩者的區(qū)別是在第二個參數(shù)的值有區(qū)別,這里就是運用了位運算。
接下來讓我們一起研究下這個位運算是個什么東西。
1、位運算概述
現(xiàn)代計算機中所有的數(shù)據(jù)是以二進制的形式存儲在設備中的。即 0、1 兩種狀態(tài),計算機對二進制數(shù)據(jù)進行的運算(+、-、*、/)都是叫位運算。
2、位運算符概覽
符號 | 描述 | 運算規(guī)則 |
---|---|---|
& | 與 | 兩個位都為1時,結(jié)果才為1 |
| | 或 | 兩個位都為0時,結(jié)果才為0 |
異或 | 兩個位相同為0,相異為1 | |
~ | 取反 | 0變1,1變0 |
<< | 左移 | 各二進位全部左移若干位,高位丟棄,低位補0 |
>> | 右移 | 各二進位全部右移若干位,對無符號數(shù),高位補0,有符號數(shù),各編譯器處理方法不一樣,有的補符號位(算術(shù)右移),有的補0(邏輯右移) |
3、位運算實現(xiàn)權(quán)限組合
既然位運算是以二進制數(shù)據(jù)做運算,因此我們可以用二進制數(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)定義了讀、寫、刪三個單獨權(quán)限。如果要定義一個讀寫權(quán)限,需要怎么定義呢。
根據(jù)|
運算符的規(guī)則可知,當兩個位中只要有一個為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)限切換
當用戶擁有讀權(quán)限,就刪除用戶的讀權(quán)限;當用戶沒有讀權(quán)限,就添加讀權(quán)限。這樣的權(quán)限切換,要怎么實現(xiàn)呢。
根據(jù)^
運算符規(guī)則可知,當兩個位相同時為0,相異為1。
// 當兩個值相等時,結(jié)果為0。即自己與自己做異或運算時,結(jié)果為0。 0b0001 ^ 0b0001 // 0b0000 // 一個0值與目標做異或運算時,得到目標值。 0b0000 ^ 0b0001 // 0b0001
因此,要切換哪個權(quán)限,只需要與該權(quá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)限組合中是否擁有某個權(quán)限
當用戶擁有一個權(quán)限組合,怎么判斷用戶是否擁有某個權(quán)限呢。
根據(jù)&
運算符規(guī)則可知,當兩個位都為1時結(jié)果為1,否則結(jié)果為0。
// 自己與自己做與運算時,結(jié)果為自己。 0b0001 & 0b0001 // 0b0001 // 一個0值與目標做與運算時,結(jié)果為0。 0b0000 & 0b0001 // 0b0000
因此,要判斷是否擁有某個權(quán)限,只需要與該權(quá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)限組合中的某個權(quán)限
如果用戶擁有讀寫權(quán)限,想要刪掉用戶的讀權(quán)限,需要怎樣實現(xiàn)呢。
由以上可知,需要先判讀是否有讀權(quá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使用位運算實現(xiàn)權(quán)限組合的代碼示例的詳細內(nèi)容,更多關(guān)于JS位運算實現(xiàn)權(quán)限組合的資料請關(guān)注腳本之家其它相關(guān)文章!