Js

bitwise operator

底层库开发中可使用的二进制代替Math类操作,会提速,但失去语义话

二进制各位为 1 其他为 0 代表的数
image.png
所以往左一位就是 x 2,往右一位就是 %2

<<:左移(右边0,保留符号位),<< 1 相当于 x2

  1. -2 << 1 //-4
  2. 3 << 1 //6

>>:右移(左边补符号位,其他补0,相当于移位后还是负数), >> 1 相当于 %2
对于正数的右移操作优先使用 >>>,因为可省去符号位操作,理论更快。

  1. -2 >> 1 //-1
  2. -2 >>> 1 //2147483647

与 >> 的不同在于,左边全补0,包括符号位 所以负数的符号位没有被保留 被 0 补充,对于 正数 来说没有任何区别,较小负数 >>> 会变为一个很大的正数,因为负数越小 1 位越多

| 0:去小数位,注意与 Math.floor 对负数处理对区别

  1. 1.23|0 //1
  2. -1.2323 | 0 //-1
  3. Math.floor(1.23) //1
  4. Math.floor(-1.23) //-2

^ 1 / ^= 1:0,1切换

  1. 0 ^ 1 //1
  2. 1 ^ 1 //0
  3. 0 ^= 1 //0
  4. 1 ^= 0 //1

!~-1:-1判断,-1带小数当然也为 true
因为 1 为: 0000 … 0001
所以-1作为1的补码表示为: 1111 … 1111 全为1,所以按位非后全为 0,也就是 0,falsy

  1. !~-1 === true

& 1:奇变1 偶变0 ,所以 !!(number & 1) 可以用于判断是否为奇

  1. 121 & 1 //1
  2. 2 & 1 //0
  3. !!(121 & 1) //true

交换数

因为 ^ 操作相当于左右自有 1 位的集合 (只有一边为 1 ,保留 1,都为 1 或 都为 0 则为 0);
第一步相当于收集所有自有 1,二三步相当于舍弃所有自有 1 位,使用对方 1 位和 共有 1 位,所以实现了交换。

  1. let a = 1; b = 2;
  2. a = a^b;
  3. b = a^b; // 1
  4. a = a^b; // 2

加法

自有(只有当前操作数为 1 的位)共有(左右操作数都为 1 的位)
正数加法的本质就是 l r异或取 合位1,l r与取 进位1 ,再左移去进位,循环处理(异或取合位)进位,直到不再需要进位 合,所以可以简单得到:
^:获得左右 ,自有1位(无进位)
&:获得左右,共有1位(等待进位)

  1. function add(l, r) {
  2. while(r !== 0) {
  3. let temp = l;
  4. l = l ^ r; // 合(合1 未处理进位)
  5. // & 获取需要进位的位(两数同位 为1)
  6. // 左移1完成进位, & 后为0说明无需进位(没有同位1的位)
  7. r = (temp & r) << 1; // 取进位,循环处理直到处理完所有进位
  8. }
  9. return l;
  10. }

减法

减法就是 a - b -> a + (-b)
其实就是 右侧转符号,再相加,负数是正数的 全位取反 + 1,所以正数也是负数的 全位取反 + 1,也就是如下处理:

  1. function minus(l, r) {
  2. r = add(~r, 1)
  3. return add(l, r);
  4. }

收集

js 打包效果基准测试

https://github.com/privatenumber/minification-benchmarks
image.png