一、使用左移运算符 << 迅速得出2的次方,使用右移运算符 >> 迅速除以2的次方

1<<2 // 1*2^2=4
1<<3 // 1*2^3=8
2<<2 // 2*2^2=8

8>>1 // 8/(2^1)=4
8>>2 // 8/(2^2)=2
16>>2 // 16/(2^2)=4

二、使用 ^(按位异或) 切换变量 0 和 1

  • 异或即相同为0,不同为1
let toggle = 0;
// if 判断
if (toggle) {
    toggle = 0;
} else {
    toggle = 1;
}
// 三目运算符
toggle = toggle ? 0 : 1;

// 异或
toggle ^= 1;

三、使用&(按位与)判断奇偶性

  • 偶数 & 1 = 0
  • 奇数 & 1 = 1
8&1 //0
7&1 //1
  • 偶数的二进制末尾为0,基数的二进制末尾为1。

四、使用 !! 将数字转为布尔值

  • 所有非0的值都是true,包括负数、浮点数
!!7 //true
!!1.111 //true
!!-1 //true
!!0 //false

五、使用~、>>、<<、>>>(带符号位右移)、|来取整

  • ~(按位反)、>>(右移)、<<(左移)、>>>(带符号位右移)、|(按位或)

  • 相当于使用了 Math.floor()

  • ~是按位取反运算,~~是取反两次。 ~~的作用是去掉小数部分

  • 位运算都会转整数,注意 >>> 不可对负数取整

~~11.71 //11
11.71 >> 0 //11
11.71 << 0 //11
11.71 | 0 //11
11.71 >>> 0 //11

六、使用^(按位异或)来完成值交换

let a = 7
let b = 1
a ^= b
b ^= a
a ^= b

// 还可以通过加减运算
let a = 7
let b = 1
a = a + b;
b = a - b;
a = a - b;

// ES6,解构赋值
[a, b] = [b, a]; 

七、使用^(按位异或)判断符号是否相同

  • (a ^ b) >= 0; // true 相同; false 不相同
//符号不同
let a = 1
let b = -1
a ^ b

//符号相同
let a = 1
let b = 1
a ^ b

//符号相同
let a = 1
let b = 2
a ^ b

八、使用^(按位异或)来检查数字是否不相等

  • (a ^ b) === 0; // true 相等; false 不相等

let a = 10
let b = 10
a ^ b

九、n & (n - 1),如果为 0,说明 n 是 2 的整数幂

  • 2的整数幂二进制最高位为1,其余位为0。比如8:1000

  • 2的整数幂减1的最高位为0,其余位为1。比如7:0111
let a = 4
a & ( a - 1 )


let a = 3
a & ( a - 1 )

十、使用 A + 0.5 | 0 来替代 Math.round()

let a = 2.15
a + 0.5 | 0 


let a = 2.87
a + 0.5 | 0
  • 如果是负数,只需要-0.5
let a = -2.15
a - 0.5 | 0


let a = -2.87
a - 0.5 | 0

补充:0.1 + 0.2 的结果是 0.30000000000000004

  • JavaScript中数字的存储标准是 IEEE754 浮点数标准。代码中使用的无论是整数还是小数,都是同一种数据类型——64 位双精度浮点型

  • 所有数字以二进制存储,每个数字对应的二进制分为三段:符号位、指数位、尾数位。

  • 于存储的二进制有 64 位,其中符号位在六十四位的第一位,0 表示正数,1 表示负数。符号位之后的 11 位是指数位,决定了数字的范围。指数位之后的 52 位是尾数位,决定了数字的精度。

  •  0.1 和 0.2 用二进制表示时为 0.0001 1001 1001 1001...(1100循环) 和 0.0011 0011 0011 0011...(0011循环)。如果截取于第 52 位,就会得到一个有误差的结果。