JavaScript中使用IEEE-754 64位存儲。位操做符不能直接操做64位的值,而是將它轉換爲二進制補碼形式的32位的整數,最後再將結果轉爲64位。32位中31位表示整數的值,第32位爲符號位(0爲正數,1爲負數)。每一位由二進制數存儲,31位中的每一位的索引表示2的次冪乘與每一位的0或者1。沒有使用到的位將使用0填充。javascript
舉一個例子🌰。31的32位二進制數表示爲0000 0000 0000 0000 0000 0000 0001 1111。第32位0表示符號位,11111爲有效位。java
1 | 1 | 1 | 1 | 1 |
---|---|---|---|---|
2^4 * 1 | 2^3 * 1 | 2^2 * 1 | 2^1 * 1 | 2^0 * 1 |
16 | 8 | 4 | 2 | 1 |
負數使用二進制存儲,可是使用二進制補碼表示數組
如何求一個數的二進制補碼?post
舉一個例子🌰。如何求出-31
的二進制補碼。-31的二進制補碼的結果爲1111 1111 1111 1111 1111 1111 1110 0001。性能
0000 0000 0000 0000 0000 0000 0001 1111
複製代碼
1111 1111 1111 1111 1111 1111 1110 0000
複製代碼
1111 1111 1111 1111 1111 1111 1110 0000
+1
---------------------------------------
1111 1111 1111 1111 1111 1111 1110 0001
複製代碼
ECMAScript全部整數都是有符號位的。在無符號數中,第32位不表示符號,由於無符號數只能是正數,32位無符號數能夠表示更大的數。spa
在NaN和Infinity在位運算符中會被看成0處理。非數值類型會先使用Number()
處理,而後再應用位操做符。設計
按位非
~
會將數值的32位二進制的每一位取反(0變爲1,1變爲0)。按位非的操做符的本質取操做數的負值,而後減一。3d
// -24
~23
// -101
~100
// 9
~-10
// 100
~-101
複製代碼
舉一個例子🌰。10進行按位非以後的結果,等於-11rest
0000 0000 0000 0000 0000 0000 0000 1010
// ~ NOT
1111 1111 1111 1111 1111 1111 1111 0101
複製代碼
按位與&, 本質上將兩個操做數的32位二進制數的每一位對齊。而後按以下的規則取值,1 & 1 等於 1; 1 & 0 等於 0;0 & 1 等於0;0 & 0等於0。code
舉一個例子🌰。10和5之間進行按位與操做的結果,等於0
0000 0000 0000 0000 0000 0000 0000 1010
// & AND
0000 0000 0000 0000 0000 0000 0000 0101
// 等於
0000 0000 0000 0000 0000 0000 0000 0000
複製代碼
按位與|, 本質上將兩個操做數的32位二進制數的每一位對齊。而後按以下的規則取值,1 | 1 等於 1; 1 | 0 等於 1;0 | 1 等於1;0 | 0等於0。
舉一個例子🌰。10和5之間進行按位或操做的結果,等於15
0000 0000 0000 0000 0000 0000 0000 1010
// & OR
0000 0000 0000 0000 0000 0000 0000 0101
// 等於
0000 0000 0000 0000 0000 0000 0000 1111
複製代碼
按位異或^, 本質上將兩個操做數的32位二進制數的每一位對齊。而後按以下的規則取值,1 ^ 1 等於 0; 1 ^ 0 等於 1;0 ^ 1 等於1;0 ^ 0等於0。
舉一個例子🌰。10和5之間進行按位異或操做的結果15。
0000 0000 0000 0000 0000 0000 0000 1010
// ^ XOR
0000 0000 0000 0000 0000 0000 0000 0101
// 等於
0000 0000 0000 0000 0000 0000 0000 1111
複製代碼
左移(<<)將32位二進制向左移動指定的位數,空缺的位將會使用0填充。左移不會影響符號位
舉一個例子🌰。將5左移2位,等於20
0|000 0000 0000 0000 0000 0000 0000 0101
// <<2
0|000 0000 0000 0000 0000 0000 0001 0100
// 等於
(2^0 * 0) + (2^1 * 0) + (2^2 * 1) + (2^3 * 0) + (2^4 * 1) = 0 + 0 + 4 + 0 + 16 = 20
複製代碼
右移(>>)將32位二進制向右移動指定的位數,可是保留符號位,右移空缺的符號位使用0填充
舉一個例子🌰。將31有符號右移3位,等於3。
0|000 0000 0000 0000 0000 0000 0001 1111
// >>3
0|000 0000 0000 0000 0000 0000 0000 0011
// 等於
(2^0 * 1) + (2^1 * 1) = 1 + 2 = 3
複製代碼
無符號位右移,會將全部32位數都向右移動。對於正數來講右移和無符號位右移的結果是一致的。
舉一個例子🌰。將-31無符號右移28位。
1111 1111 1111 1111 1111 1111 1110 0001
// >>> 28
0000 0000 0000 0000 0000 0000 0000 1111
// 等於
(2^0 * 1) + (2^1 * 1) + (2^2 * 1) + (2^3 * 1) = 1 + 2 + 4 + 8 = 15
複製代碼
按位非~。將操做數取負值,並減1。對於浮點數,會直接捨棄小數的部分。好比
~11.1 === -12
。而後將結果,再次執行按位非操做,就會獲得了去除小數位的原數字,~-12 === 11
。所以咱們可使用~~代替Math.floor。
// 12
~~12.5
// 6
~~6.1
// 8
~~-8.1
複製代碼
我分別使用~~和Math.floor,對包含了10000000個浮點數的數組,進行向下取整。~~耗時386毫秒,Math.floor耗時411毫秒.
平時使用indexOf等API時,當查詢的字符串不存在時,indexOf會返回-1。可是Boolean(-1)
等於true,因此咱們在使用時一般須要添加一個判斷'字符串'.indexOf('字') > -1
,看上去並非那麼的簡潔。 -1按位非等於0,而Boolean(0)是等於false的。因此咱們能夠把不等式簡化成下面的樣子。
if ('米莉波比布朗'.indexOf('莉') > -1) {
}
// 等價於
if (~'米莉波比布朗'.indexOf('莉')) {
}
複製代碼
在瞭解這個技巧以前須要先了解兩個準則:
// 0
100 ^ 100
// 0
-99 ^ -99
// 100
100 ^ 0
// -2
0 ^ -2
複製代碼
在代碼中交換兩個變量的值,一般是經過第三個變量,或者使用ES6中的解構賦值
// 使用第三個變量
var a = 1
var b = 2
var c = a
a = b
b = c
// 使用解構賦值
var x = 1
var y = 2
[x, y] = [y, x]
複製代碼
使用異或按位運算符
let a = 2
let b = 3
a = a ^ b
// b = a ^ b ^ b => a ^ (b ^ b) => a ^ 0 = a
b = a ^ b
// a = a ^ b ^ a ^ b ^ b => (a ^ a) ^ (b ^ b) ^ b => 0 ^ 0 ^ b => 0 ^ b = b
a = a ^ b
複製代碼
使用異或按位運算符,能夠用來切換二進制數中的某些位,這基於這樣一個事實:
let a = 1
// 0
a = 1 ^ 1
// 1 (又變回了1)
a = a ^ 1
複製代碼
舉一個例子🌰,let a = 0b101011
, 咱們想將中間的四位進行切換(0->1, 1->0)變爲0b110101
。咱們建立一個掩碼,首尾爲0,中間四位爲1, 使用掩碼進行按位異或的操做。
// 掩碼
let mask = 0b011110
let a = 0b101011
// 0b110101
a ^ mask
複製代碼
使用按位與&, 能夠用來關閉二進制數中的某些位,這基於這樣一個事實:
好比咱們有一個8位的二進制數,咱們須要關閉後4位(設置爲0),咱們首先建立一個8位的位掩碼,位掩碼的後四位設置爲0,前四位設置爲1。接下來使用位掩碼與操做數進行按位與操做
const mask = 0b00001111
// 結果00001010,成功將後四位設置爲0
mask & 0b10101010
複製代碼
可使用按位與,檢查二進制數中某一位是否設置了。
舉一個例子🌰,咱們須要檢查第五位是否有數字。
const mask = 0b10000
// false
0b100010 & mask === mask
// true
0b110010 & mask) === mask)
複製代碼
奇數與偶數的二進制表示的特性:
// 0b0
0
// 0b1
1
// 0b10
2
// 0b11
3
// 0b100
4
// 0b101
5
// 0b110
6
複製代碼
因此咱們可使用0001做爲掩碼,使用0關閉高位,只保留第一位。當number & 1 === 1
, number爲奇數。number & 1 === 0
, number爲偶數。
// 奇數
(3 & 1) === 1
// 偶數
(4 & 1) === 0
複製代碼
ps:😂在工程中,最好不要這樣寫,省得的被打。
左移1位,等於乘以2,左移2位,等於乘以4。可是對於乘以7或者乘以9該怎麼辦呢?乘以7,能夠分解爲左移3位並減去一位,
a * 7 === (a << 3) - a
。乘以9,能夠分解爲左移3位並加上一位a * 9 === (a << 3) + a
a * 2 === a << 1
a * 3 === (a << 1) + a
a * 4 === a << 2
複製代碼
a / 2 === a >> 1
a / 4 === a >> 2
a / 8 === a >> 3
複製代碼