邏輯運(yùn)算符
1.&& 邏輯與
a && b
運(yùn)算邏輯:
a && b, 若 a 為 false 則返回 a, 若 a 為 true 則返回 b
console.log(3 && 1) // 1
console.log(0 && 1) // 0
// ps: 0為false
總結(jié):假前真后
2.|| 邏輯或
a || b
運(yùn)算邏輯:
a || b, 若 a 為 false 則返回 b, 若 a 為 true 則返回 a
console.log(3 || 1) // 3
console.log(0 || 1) // 1
console.log('' || true) // true
// ps: ''空字符串在js中也會被判定為false
console.log(!!'') // false
總結(jié):真前假后
3.! 邏輯非
!a
運(yùn)算邏輯:
若 a 為 true, 則返回 false, 反之亦然
console.log(!1) // false
若要顯式的返回變量的布爾值則可以使用 !! 雙重非運(yùn)算符 來運(yùn)算
console.log(!!1) // true
console.log(!!0) // false
需要注意的是在JS中會被轉(zhuǎn)換為 false 的表達(dá)式有:
- null
- undefined
- NaN
- 0
- 空字符串("" or '' or ``)
總結(jié): 取反
位運(yùn)算符
其實(shí)位運(yùn)算符是所有語言通用的運(yùn)算符弧可,偷懶起見還是寫在了JS分類下哈哈哈
位運(yùn)算符都需要將運(yùn)算符前后的數(shù)轉(zhuǎn)為二進(jìn)制再運(yùn)算, 所謂的位是二進(jìn)制數(shù)的位數(shù)
1.| 按位或運(yùn)算符
a | b
運(yùn)算規(guī)則:
0|0=0带族;0|1=1糊肠;1|0=1轻纪;1|1=1侨把;即: a 和 b 的對應(yīng)二進(jìn)制位只要有一個為1兄旬,其值為1赖瞒。
console.log(3 | 4) // 7
// 3轉(zhuǎn)為二進(jìn)制0011, 4轉(zhuǎn)為二進(jìn)制0100, 所以結(jié)果為0111, 輸出7
console.log(31 | 2) // 31
// 31 -> 00011111 2 -> 00000010, 結(jié)果為00011111, 輸出31
實(shí)際應(yīng)用:
可用于小數(shù)取整
//后面為0時取小于該小數(shù)的最大整數(shù)
console.log(3.1 | 0) // 3
// 所有的位運(yùn)算只會對小數(shù)起作用所以 3.1 | 0 會自動舍去小數(shù)部分達(dá)到取整效果
// 相當(dāng)于 Math.floor(3.1);
2.& 按位與運(yùn)算符
a & b
運(yùn)算規(guī)則:
0&0=0; 0&1=0; 1&0=0; 1&1=1; 即:a 與 b 的對應(yīng)二進(jìn)制位同時為“1”翁逞,結(jié)果才為“1”总珠,否則為0.
console.log(3 & 4) // 0
console.log(31 & 2) // 2
3.~ 取反運(yùn)算符
~a
運(yùn)算規(guī)則:
將a按二進(jìn)制位取反, 即將0變1, 1變0, 然后將二進(jìn)制數(shù)變?yōu)楦↑c(diǎn)數(shù)
console.log(~25) // -26
// 00000000000000000000000000011001 -> 11111111111111111111111111100110 -26
// 就像是將正數(shù)變負(fù), 再取其反碼
從表現(xiàn)上而言 ~ 是對數(shù)字求負(fù), 然后減 1, 因此 25 變 -26.
4.^異或運(yùn)算符
a ^ b
運(yùn)算規(guī)則:
0^0=0; 0^1=1; 1^0=1; 1^1=0; a 和 b 办绝,按二進(jìn)制位進(jìn)行“異或”運(yùn)算。
^ 運(yùn)算符滿足如下運(yùn)算規(guī)則
- 交換律:AB=BA
- 結(jié)合律:ABC=A(BC)=(AB)C
- 自反律:ABB=A^0=A
- X^X=0 ,X^0=X
console.log(23^3) // 20
// 23 -> 00010111 3 -> 00000011 異或后為 00010100 -> 20
5. << 左移運(yùn)算符
a << b
運(yùn)算規(guī)則:
將a的各二進(jìn)制位全部左移b位(左邊的b個二進(jìn)制位丟棄姚淆,右邊補(bǔ)0)孕蝉。
console.log(3 << 2) // 12
// 3 -> 0011 運(yùn)算結(jié)果為 1100 -> 12
就結(jié)果而言, 左移運(yùn)算符 << 便是 a 乘上 2 的 b 次方
6. >> 右移運(yùn)算符
運(yùn)算規(guī)則:
將a的各二進(jìn)制位全部右移b位(右邊的b個二進(jìn)制位丟棄,若是正數(shù), 左邊補(bǔ)0, 若是負(fù)數(shù)則補(bǔ)1, 及補(bǔ)其符號位的數(shù))腌逢。
console.log(12 >> 2) // 3
console.log(12 >> 4) // 0
// 3 -> 0011 運(yùn)算結(jié)果為 1100 -> 12
就結(jié)果而言, 右移運(yùn)算符 << 便是 a 除以 2 的 b 次方, 若 2 的 b 次比 a 要大, 結(jié)果最小為 0
此時會有小伙伴問了, 普通整型是只有32位的, 如果 b 的值大于32或者小于0會怎么運(yùn)算啊
那我們不妨來試試
console.log(4 << 34) // 16
4 向左移位34位照理來說已經(jīng)超出了原位數(shù), 但是輸出結(jié)果為16相當(dāng)于左移兩位 34 - 32 = 2,
說到這應(yīng)該明白了吧, 不過不清楚是走過了循環(huán)還是運(yùn)行js的引擎自動將b%32
console.log(4 << -30) // 16
其實(shí)看到這里也大概知道左移負(fù)數(shù)位的規(guī)則了吧, -30 + 32 = 2, 同樣也是4 << 2 = 16
不同長度的數(shù)據(jù)進(jìn)行位運(yùn)算
如果兩個不同長度的數(shù)據(jù)進(jìn)行位運(yùn)算時降淮,系統(tǒng)會將二者按右端對齊,然后進(jìn)行位運(yùn)算搏讶。
我們知道在C語言(此處拿C舉例, 畢竟JS沒有l(wèi)ong int之分..)中l(wèi)ong型占4個字節(jié)佳鳖,int型占2個字節(jié),如果一個long型數(shù)據(jù)與一個int型數(shù)據(jù)進(jìn)行“與”運(yùn)算媒惕,
右端對齊后系吩,左邊不足的位依下面三種情況補(bǔ)足,
- 如果整型數(shù)據(jù)為正數(shù)妒蔚,左邊補(bǔ)16個0穿挨。
- 如果整型數(shù)據(jù)為負(fù)數(shù)月弛,左邊補(bǔ)16個1。
- 如果整形數(shù)據(jù)為無符號數(shù)科盛,左邊也補(bǔ)16個0帽衙。