二进制、位运算在代码中的巧妙应用

860 阅读2分钟

用法示例

场景:在一个系统中,用户一般有查询(Select)、新增(Insert)、修改(Update)、删除(Delete)四种权限,四种权限有多种组合方式,也就是有16中不同的权限状态(2的4次方)。

如果使用位掩码的方式,只需要用一个大于或等于0且小于16的整数(二进制更直观)即可表示所有的16种权限的状态。

/**
 * @关于二进制运算
 * & 交集 两个都为1时值为1
 * | 并集 两个都为0时值为0
 * ^ 异或 相同为0,相异为1
 * ~ 取反 0变1,1变0 
 *(题外话:按位取反的计算结果:~n = -(n+1) ,原因参照负数的二进制表示<用补码表示负数>
 https://blog.csdn.net/u013291076/article/details/84950188)
 */

/**
 * @权限说明
 * 用二进制表示拥有的权限集合:0表示无权限,1表示有权限
 * 例如:0b0011  --- 拥有增加和删除权限(参照Permission类的静态属性)
 * 
 *   value  查  改  删  增
 *  0b0001  0   0   0   1   ALLOW_INSERT - 只允许增加
 *  0b0010  0   0   1   0   ALLOW_DELETE - 只允许删除
 *  0b0100  0   1   0   0   ALLOW_UPDATE - 只允许修改
 *  0b1000  1   0   0   0   ALLOW_SELECT - 只允许查询
 *  0b0011  0   0   1   1   允许增加和删除
 *  ...
 * 
 * 使用位掩码的方式,只需要用一个大于或等于0且小于16的整数即可表示所有的16种权限的状态。
 */


class Permission {
    // 静态属性:static关键字在ES7中引入,babel已支持转码
    static ALLOW_INSERT = 0b0001; // 1<<0
    static ALLOW_DELETE = 0b0010; // 1<<1  
    static ALLOW_UPDATE = 0b0100; // 1<<2
    static ALLOW_SELECT = 0b1000; // 1<<3
        
    constructor(permission) {
        this.value = permission || 0b0000;
    }

    getPermission() {
        // 返回二进制表示
        return this.value.toString(2);
    }

    // 添加一些权限 
    enable(permission) {
        this.value |= permission;
    }

    // 剪除一些权限 
    disable(permission) {
        // 或者 this.value = this.value ^ (this.value & permission);
        this.value &= ~permission;
    }

    // 是否拥有某些权限
    isAllow(permission) {
        // eg: 0b1100 & 0b1000 === 0b1000 
        return (this.value & permission) === permission;
    }

    // 是否禁用了某些权限
    isNotAllow(permission) {
        // eg: 0b1100 & 0b0001 === 0 
        return (this.value & permission) === 0;
    }

    // 是否只拥有某项权限
    isOnlyAllow(permission) {
        return this.value === permission;
    }

    //可以可无
    isAllowInsert() {
        return this.isAllow(Permission.ALLOW_INSERT);
    }

    isAllowDelete() {
        return this.isAllow(Permission.ALLOW_DELETE);
    }

    isAllowUpdate() {
        return this.isAllow(Permission.ALLOW_UPDATE);
    }

    isAllowSelect() {
        return this.isAllow(Permission.ALLOW_SELECT);
    }
}

/**
* 用法举例
*/

// 创建一个新的权限集合
let permission = new Permission(Permission.ALLOW_INSERT | Permission.ALLOW_SELECT);
// 判断是否有增加和删除的权限
permission.isAllow(Permission.ALLOW_INSERT | Permission.ALLOW_DELETE); // false;
// 增加删除权限
permission.enable(Permission.ALLOW_DELETE);
// 禁用删除权限
permission.disable(Permission.ALLOW_DELETE);