本文共--字 阅读约--分钟 | 浏览: -- Last Updated: 2021-07-03
// 十进制 => 二进制
let num = 10;
console.log(num.toString(2)); // 1010
// 二进制 => 十进制
let num1 = 1001;
console.log(parseInt(num1, 2)); // 9
按位或: 1 | 1 = 1
, 1 | 0 = 1
, 0 | 0 = 1
。
function toInt(num) {
return num | 0;
}
按位与: 1 & 1 = 1
, 1 & 0 = 0
, 0 & 0 = 0
。
// 奇数的二进制最后一位必然为1,所以任意一个奇数 & 1 一定等于1。
function fn(num) {
return num & 1;
}x
将权限使用 2^n 次方表示, 因为其对应的二进制为 0001
, 0010
等等,只有一位为1,不同权限取不同位的1。
添加权限 按位或 即可,00100000 | 00000010 = 00100010
;
按位异或,00100010 ^ 00000010 = 00100000
/ 00100000 ^ 0000010
= 00100010
更合适有就删除没有就添加这种场景。
删除权限为 00100010 & (~00000010)
= 00100010 & 11111101
= 00100000
;
enum Permission {
/** 读取权限 */
READ = 0b0001,
/** 修改权限 */
WRITE = 0b0010,
/** 删除权限 */
DELETE = 0b0100,
/** 新增权限 */
ADD = 0b1000,
}
class UserPermission {
/** 用户权限 */
public userPermission: number;
constructor(userCode?: number) {
this.userPermission = userCode || 0;
}
addPermission(permission: Permission) {
this.userPermission = this.userPermission | permission;
}
deletePermission(permission: Permission) {
this.userPermission = this.userPermission & (~permission);
}
}
const u = new UserPermission();
u.addPermission(Permission.READ);
console.log(u.userPermission); // 1
u.addPermission(Permission.DELETE);
console.log(u.userPermission); // 5
u.deletePermission(Permission.READ);
console.log(u.userPermission); // 4
上述方案的局限性就是,权限码只能是 1, 2, 4, 8,…,1024,… 那么最多只能有32中权限码,在较为复杂的场景就不适用了。
权限空间:
权限code, 使用 index, pos
来表示, index
表示权限空间, pos
表示在二进制中1
的位置,从0开始, pos
为5, 则二进制为 00100000 = 2 ^ 5 = 32
; 权限码2, 8
代表权限空间2中的 8
权限。
用户权限,如果有3个权限空间, 用户权限字符串为1, 17, 8
, 说明对应的权限码是 0,1
、1,1
、1,4
、 2,3
enum Permission {
/** 系统权限 */
SYSTEM_PERMISSION = '0,0',
/** 相册权限 */
SYSTEM_PHOTO_PERMISSION = '0,1',
/** 定位权限 */
SYSTEM_POSITION_PERMISSION = '0,2',
/** 麦克风权限 */
SYSTEM_MICROPHONE_PERMISSION = '0,3',
/** 数据库管理权限 */
DATA_MANAGE = '1,0',
/** 数据库管理权限 */
DATA_ADD = '1,1',
/** 数据库管理权限 */
DATA_DELETE = '1,2',
/** 数据库管理权限 */
DATA_UPDATE = '1,3',
/** 数据库管理权限 */
DATA_GET = '1,4',
/** 接口权限 */
/** 数据库管理权限 */
INTERFACE_ADD = '2,0',
/** 数据库管理权限 */
INTERFACE_DELETE = '2,1',
/** 数据库管理权限 */
INTERFACE_UPDATE = '2,2',
/** 数据库管理权限 */
INTERFACE_GET = '2,3',
}
interface HandlePermission {
/** 当前需要操作的权限空间 */
index: number;
/** 用于生成当前权限的权限码 */
pos: number;
/** 当前权限空间已有的权限码是 */
currentZoneCode: number;
/** 当前用户权限字符串切割成的字符串数组 */
userPermission: string[];
}
class UserPermission {
/** 用户权限 */
public userPermission: string;
constructor(userCode?: string) {
this.userPermission = userCode || '';
}
/** 增加权限 */
addPermission(permission: Permission) {
// currentZoneCode 指当前在 index 权限空间的权限字符串
const { index, pos, currentZoneCode, userPermission } = this.handlePermission(permission);
userPermission[index] = `${currentZoneCode | Math.pow(2, pos)}`
this.userPermission = userPermission.join(',');
// 举例
// 如果当前权限为 4,8,1 ,添加权限 2,3
// 这里的 index = 2, pos = 2, currentZoneCode = 1, userPermission = [4, 8, 1]
// userPermission[2] = 1 | (2 << 3) = 9
// userPermission = [4,8,9].join(',')
// 对应权限就是 0,2 、 1,3 、 2,0 、2,3
}
/** 删除权限 */
deletePermission(permission: Permission) {
const { index, pos, currentZoneCode, userPermission } = this.handlePermission(permission);
userPermission[index] = `${currentZoneCode & (~Math.pow(2, pos))}`
this.userPermission = userPermission.join(',');
}
/** 判断是否有该权限 */
hasPermission(permission: Permission) {
const { pos, currentZoneCode } = this.handlePermission(permission);
const target = Math.pow(2, pos)
return (currentZoneCode & target) === target;
// 举例
// 如果当前权限为 7,8,1 ,判断权限 0,4
// 这里的 currentZoneCode = 7, pos = 4;
// 7 & 16 === 16 的比较是 false
// 如果判断 0,2 结果就是 7 & 4 = 4 就是 true; 7代表着 0,0 0,1 0,2
}
/** 处理 Permission 为 数字型数组 */
handlePermission(permission: Permission): HandlePermission {
const [index, pos] = permission.split(",");
// 取出当前的用户权限转换为 字符串数组
const userPermission: string[] = this.userPermission ? this.userPermission.split(",") : [];
// 根据 index 取出 当前用户在index空间所拥有的权限,然后进行添加权限运算
const currentZoneCode = Number(userPermission[+index] || 0);
return {
index: +index,
pos: +pos,
currentZoneCode: currentZoneCode,
userPermission: userPermission,
}
}
/** 根据 权限码 还原权限 */
togglePermission() {
const results: string[] = [];
if (!this.userPermission) {
return results;
}
Object.keys(Permission).forEach((key) => {
const value: Permission = (Permission as any)[key]
if (this.hasPermission(value)) {
results.push(key)
}
})
return results;
}
/** log 打印当前所拥有的权限 */
log() {
console.log('当前userPermission: %s', this.userPermission);
console.log('当前权限为: %s', this.togglePermission().join(','));
}
}
const u = new UserPermission();
u.addPermission(Permission.DATA_ADD);
u.log();
// 当前userPermission: ,2
// 当前权限为: DATA_ADD
u.addPermission(Permission.SYSTEM_MICROPHONE_PERMISSION);
u.log();
// 当前userPermission: 8,2
// 当前权限为: SYSTEM_MICROPHONE_PERMISSION,DATA_ADD
u.addPermission(Permission.INTERFACE_UPDATE);
u.log();
// 当前userPermission: 8,2,4
// 当前权限为: SYSTEM_MICROPHONE_PERMISSION,DATA_ADD,INTERFACE_UPDATE
u.deletePermission(Permission.INTERFACE_UPDATE);
u.log();
// 当前userPermission: 8,2,0
// 当前权限为: SYSTEM_MICROPHONE_PERMISSION,DATA_ADD
const has1 = u.hasPermission(Permission.INTERFACE_ADD);
console.log(has1); // false
const has2 = u.hasPermission(Permission.SYSTEM_MICROPHONE_PERMISSION);
console.log(has2); // true
/** num为 0 / 1 */
function toggle(num) {
return num ^ 1;
}
if (~arr.indexOf(item)) { // 存在
// code
}
对任一数值 x 进行左移n位,等同于 x * 2^n
3 << 2 = 12
对任一数值 x 进行右移n位,等同于 x / 2^n,然后取整
64 >> 2 = 16
// rgb(255, 255, 255) => '#ffffff'
// 先将rgb转换为 十进制,再使用toString(16)转换为十六进制
// 第三个 255 => 0000ff
// 第二个 255 => 255 * 16^2 => 00ff00 16^2 = (2^4)^2 = 2^8
// 第二个 255 => 255 * 16^4 => ff0000
// 由于 | 运算在二进制对位在同步补位的时候就相当于是 累加
function rgbToHex(rgb){
// 取出rgb中的数值
let arr = rgb.match(/\d+/g);
if (!arr || arr.length !== 3) {
console.error('rgb数值不合法');
return
}
let hex = (arr[0] << 16 | arr[1] << 8 | arr[2]).toString(16);
return `#${hex.padStart(6, '0')}`;
}
// ffffff = 16777215
// 16777215 的 二进制 111111111111111111111111 共24位
// 当右移16位,即前8位的十进制。
// 当右移8位,即前16位的十进制,在跟 0xff = 255 = 1111111 进行与运算,即取出这16位中的后8位(即中间8位的)十进制
// 当直接与 0xff进行与运算,即取出24位中的后8位的十进制
function hexToRgb(hex) {
let num = hex.replace('#', '0x');
let r = num >> 16;
let g = num >> 8 & 0xff;
let b = num & 0xff;
return `rgb(${r},${g},${b})`;
}