使用位运算进行高效率的枚举

38

先进行知识准备:

  1. << 符号是 Javascript 中的位操作符,1 << N 的意思是: 将数字 1 的位向左移动 N

    例如:

    1 << 1 // 2
    // 二进制:1 => 10
    1 << 2 // 4
    // 二进制:10 => 100
    ...
    1 << N // 2的N次方
    
  2. |Javascript 中的位运算符:
    当两个数值进行 | 运算时,会对每一位进行比较,任何一位上,如果两个数都为 0,则结果为 0;其余情况结果为 1;

    例如:

    1 << 1 | 1 << 2 // 010 | 100
    // 结果为 110,即数字:6
    
    1 | 1 << 3 // 0001 | 1000
    // 结果为 1001,即数字:9
    
  3. &Javascript 中的运算符: 。 当两个数值进行 & 运算时,会对每一位进行比较,任何一位上如果两个数都为 1,则结果为 1;其余情况结果为 0;

    例如:

    1 & 9 // 0001 & 1001 = 0001 (1)
    
    2 & 8 // 0010 & 1000 = 0000 (0)
    

知识准备完成,开始战斗:

假设一个场景:当我们面试一个前端同学时,我们需要知道他有哪些技能。

先定义一下各项技能:

/**
 * SKILLS:面试者的技能枚举
 **/
const SKILLS = {
  CSS: 1 , // 0001
  JS: 1 << 1, // 0010
  HTML: 1 << 2, // 0100
  WEB_GL: 1 << 3 // 1000
}

然后我们需要标记他有哪些技能,这个添加标记的过程如下:

let skills = 0
// 增加一项他会的技能
function addSkill(skill) {
  skills = skills | skill // 加上
}

addSkill(SKILLS.CSS) // 0001
addSkill(SKILLS.HTML) // 0101
addSkill(SKILLS.WEB_GL) // 1101

完成了技能的添加,我们就需要在其他地方开销这个人具备什么技能了,开销过程如下:

// 判断他是否会 CSS
SKILLS.CSS & skills // 1 (0 代表不会,非0代表会)

// 判断他是否会 JS
SKILLS.JS & skills // 0 (0 代表不会,非0代表会)


// 判断他是否会 HTML 且会 WebGl
SKILLS.HTML & skills && SKILLS.WEB_GL & skills // 8 (0 代表不会,非0代表会)

// 判断他是否会 JS 或会 HTML
SKILLS.JS & skills || SKILLS.HTML & skills