前言
在判断分支中使用符号”&“和”&&”作为逻辑判断是经常见的,但是这两者又有什么区别呢?
他们分别代表的位运算符和逻辑运算符又有什么区别呢?
位操作符
位操作符用于在最基本的层次上,即按内存中表示数值的位来操作数值
补充知识点 负数存储
负数同样是以二进制存储 但使用的格式是二进制补码
计算一个数值(负数)的二进制补码,需要经过三个步骤
1)求这个数值绝对值的二进制码 例如 要求 -18的二进制补码 先求出18的二进制码
2)求二进制反码 即将0换为1 1换为0
3)最后二进制反码 + 1

1 按位非( ~ )
执行按位非的结果就是返回数值的反码
~25 = -26
~10 = -11
~-10 = 9
然后我们发现了规律 好像就是 这个数的负数减一
我们知道一个数的负数二进制存储是 该数取反 +1 那么很容易推出一个数的反码就是 该数的负数 -1
2 按位与( & )
按位与只有在两个数值的对应位都是1时才返回1 任何一位是0 结果都是0
0b110 & 0b011 // 2
25 & 3 // 1

3 按位或( | )
只有两个数值的对应位都是0的情况下才返回0 否则返回1
0b110 | 0b011 // 0b111 => 7
0b001 | 0b011 // 0b011 => 3
4 按位异或( ^ )
这两个数值的对应位上有一个1时才返回1 否则返回0
0b011 ^ 0b0101 // 0b0110 => 6
25 ^ 3 // 26

异或的应用
任何数和0异或得到他本身 和自己异或得到0
15 ^ 0 // 15
15 ^ 15 // 0
5 左移( << )
这个操作符会将所有位向左移动指定的位数
向左移动后原始值的右侧会多出空位,左移操作会用0来填充这些空位
以便得到的结果是一个32位的二进制数
2 << 5 // 64 10 => 1000000
需要注意的是,左移不会影响操作数的符号位
-2 << 5 // - 64
左移的应用
左移一位相当于在右边补一个0 相当于原数 * 2
2 << 1 // 4
5 << 1 // 10
6 有符号的右移( >> )
有符号的右移会将所有位向右移动 但保留符号位
有符号的右移与左移相反
64 >> 5 // 2 1000000 => 10
移动过程中也会出现空位 不过空位是出现在原数值的左侧 符号位的右侧 而此时ES会用符号位的值来填补空位
7 无符号的右移( >>> )
这个操作会将所有的32位都像右移动 即符号位也右移
无符号右移是以0来填充空位
所以,对正数来说, 无符号的右移与有符号右移的结果相同
64 >> 5 // 2
64 >>> 5 // 2
但对于负数来说,情况就不一样了
-64 >>> 5 // 134217726
因为负数是以其绝对值的二进制补码表示,无符号右移会把这个二进制当做正数表示,所以会导致右移后的结果非常大
逻辑操作符
逻辑运算符用于进行逻辑运算的,他的返回值只有true和false
逻辑非( ! )
逻辑非首先会操作数转换为对应的布尔值,然后对其求反
我们知道js中有五大falsy值 分别是 NaN 0 空字符串 undefined null
所以对这五个falsy值取反得到的是true
!undefined // true
!null // true
!'' // true
!0 // true
!NaN // true
需要注意的是js中 空数组和空对象对应的布尔值都是true
!{} // false
![] // false
使用两次逻辑非就可以得到一个数的布尔值 相当于Boolean()函数
!!{} // true
!!0 // false
!!undefined // false
逻辑或( || )
两个表达式只要有一个是true 那么结果就是true
短路操作符 如果第一个表达式结果是true 那么就不会看第二个表达式
2 > 3 || 3 < 5 // true
2 > 3 || 3 > 5 // false
false || true // true
false || false // false
逻辑与( && )
只有两个表达式结果都为true 结果才为true 否则为false
短路操作符 如果第一个表达式是false 那么直接返回false 不会看第二个表达式
2 > 3 && 3 < 5 // false
2 > 3 && 3 > 5 // false
2 < 3 && 3 < 5 // true
false && true // true
true && true // true