Javascript中的 “&” 和 “|” 詳解
轉自:https://www.jb51.net/article/104394.htm
一、前言:
在文章開始之前,先出幾個題目給大家看看:
var
num1 = 1 & 0;
console.log(num1);
// 0
var
num2 =
'string'
& 1;
console.log(num2); // 0
var
num3 =
true
& 1;
console.log(num3);
// 1
var
num4 = undefined |
false
;
console.log(num4);
// 0
var num5 = undefined |
true
;
console.log(num5);
// 1
var
num6 = 23 & 5;
console.log(num6);
// 5
var
num7 = 23 | 5;
console.log(num7); // 23
|
上面的題目大家都做對了嗎?我們之前有總結過 《淺談javascript中的 “ && ” 和 “ || ” 》,"&&” 和 “||” 是邏輯運算表示式中的操作符。那麼一個 “&” 或者一個 “|” 又代表什麼含義呢?有什麼特性呢?接下來,我們就來一一揭祕。
首先,我們得清楚 “&” 和 “|” 是位運算操作符。
位運算子用於在最基本的層次上,即按記憶體中表示數值的位來運算元值。ECMAScript中的所有數值都以IEEE-754 64位格式儲存,但位操作符並不直接操作64位的值。而是先將64位的值轉換成32位的整數,然後執行操作,最後再將結果轉換為64位。對於開發人員來說,由於64位儲存格式是透明的,因此整個過程就像是隻存在32位的整數一樣。
對於有符號的整數,32位中的前31位用於表示整數的值。第32位表示數值的符號:0表示正數,1表示負數。這個表示符號的位叫做符號位,符號位的值決定了其他位數值的格式。其中,正數以純二進位制格式儲存,31位中的每一位都表示2的冪。第一位(叫做位0)表示20,第二位表示21,以此類推。沒有用到的位以0表示,即忽略不計。例如,數值18的二進位制表示是0000 0000 0000 0000 0000 0000 0001 0010,或者更簡潔的10010。這是5個有效位,這5位本身就決定了實際的值。
負數同樣以二進位制碼儲存,但使用的格式是二進位制補碼。計算一個數值的二進位制補碼,需要經過下列3個步驟:
(1)求這個數值絕對值的二進位制碼(例如,要求-18的二進位制補碼,先求18的二進位制碼);
(2)求二進位制反碼,即將0替換為1,將1替換為0;
(3)得到的二進位制反碼加1。
這樣,求得了-18的二進位制表示,即1111 1111 1111 1111 1111 1111 1110 1110。
......在ECMAScript中,當對數值應用位操作符時,後臺會發生如下轉換過程:64位的數值被轉換成32位數值,然後執行位操作,最後再將32位的結果轉換回64位數值。這樣,表面上看起來就好像是在操作32位數值,就跟在其他語言中以類似方式執行二進位制操作一樣。但這個轉換過程也導致了一個嚴重的副效應,即在對特殊的NaN和Infinity值應用位操作時,這兩個值都會被當成0來處理。
如果對非數值應用位操作符,會先使用Number()函式將該值轉換為一個數值(自動完成),然後再應用位操作。得到的結果將是一個數值。 ......(擷取自《Javascript高階程式設計》)
二、“&”(按位與AND):
按位與操作符由一個和號字元(&)表示,它有兩個操作符數。從本質上來講,按位與操作就是將兩個數值的每一位對齊,對相同位置上的兩個數執行AND操作。
按位與AND操作規則:只有兩個數值的對應位都是1時才返回1,任何一位是0,結果都是0。
前面已經把理論性的東西說的太多了,但是我覺得理論又很有必要。接下來,直接分析例子吧!
我們先看上面題目中的 num1,num2,num3以及num6。我們嘗試結合上面的理論來分析為什麼會輸出最終的結果。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
// num1是1和0進行“按位與”操作後的返回值。1的二進位制碼簡寫為1,0的二進位制碼簡寫為0,根據上面的規則,第二個操作符數為0,結果是0
var
num1 = 1 & 0;
console.log(num1);
// 0
// 第一個操作符數是字串,按照前言裡面的理論,對於非數值的操作符數,先使用Number()函式處理,結果返回NaN,NaN又會被當成0來處理。所以最終結果也是0
var
num2 =
'string'
& 1;
console.log(num2);
// 0
// true是布林型別值,同樣使用Number()函式處理,處理後得到數值1,於是表示式就相當於“1 & 1” 進行位運算,當兩個數值都為1的時候,結果返回1
var
num3 =
true
& 1;
console.log(num3);
// 1
// 23的二進位制碼是:...10111,5的二進位制碼是:...00101。然後每一位進行對齊處理,結合上面的規則,可以得出10111&00101的結果是:00101。00101就是5
var
num6 = 23 & 5;
console.log(num6);
// 5
// 再加個例子:24的二進位制碼為...11000,7的二進位制碼為...00111,相同位置的兩個數執行AND操作,結果發現結果是...00000。所以最終結果是0,你算對了嗎?
var
add1 = 24 & 7;
console.log(add1);
// 0
|
三、“|”(按位或OR):
按位或操作符由一個豎線符號(|)表示,同樣有兩個操作符數。從本質上來講,按位或操作也是將兩個數值的每一位對齊,對相同位置上的兩個數執行OR操作。
按位或OR操作規則:只要兩個數值的對應位有一個是1就返回1,而只有在兩個位都是0的情況下才返回0。
我們接最上面的例子來看吧!
// 第一個操作符數為undefined,第二個操作符數是false,均不是數值,所以都要先使用Number()函式處理,處理結果都是返回NaN,NaN又會被當成0處理,於是最終結果是0
var
num4 = undefined |
false
;
console.log(num4);
// 0
// 第一個操作符數相當於0,第二個操作符數相當於1,結合按位或的規則,最終結果是1
var
num5 = undefined |
true
;
console.log(num5);
// 1
// 23的二進位制碼是:...10111,5的二進位制碼是:...00101。然後每一位進行對齊處理,結合上面的規則,可以得出10111|00101的結果是:10111。10111就是23
var
num7 = 23 | 5;
console.log(num7);
// 23
// 再加個例子:24的二進位制碼為...11000,7的二進位制碼為...00111,相同位置的兩個數執行AND操作,結果發現結果是...11111。所以最終結果是31,你算對了嗎?
var
add2 = 24 | 7;
console.log(add2);
// 31
|
四、其他:
相信也會有一些朋友不知道怎麼把數值轉換成標準的二進位制碼,那麼有沒有快速的方法呢?答案是肯定的。
我的網上隨機找到了一個線上轉換工具地址:數值進位制轉換(點我檢視)。(當然,你也可以使用你找到的別的工具,不管怎樣,能實現效果就是我們的最終目的)
最後,再附上我通過手寫轉換二進位制過程中總結的規律圖,依然可以快速將數值轉換成二進位制碼,逼格滿滿噠!
四、其他:
相信也會有一些朋友不知道怎麼把數值轉換成標準的二進位制碼,那麼有沒有快速的方法呢?答案是肯定的。
我的網上隨機找到了一個線上轉換工具地址:數值進位制轉換(點我檢視)。(當然,你也可以使用你找到的別的工具,不管怎樣,能實現效果就是我們的最終目的)
最後,再附上我通過手寫轉換二進位制過程中總結的規律圖,依然可以快速將數值轉換成二進位制碼,逼格滿滿噠!
後,再附上我通過手寫轉換二進位制過程中總結的規律圖,依然可以快速將數值轉換成二進位制碼,逼格滿滿噠!