最近學習KnockOut.js的時候,有個案例設計到>>>=和 |=的用法問題,其實>>>和|是位運算符,num >>>= 1等同於num =num >>>1;同理Modes |= CharMode(sPW.charCodeAt(i))等同於Modes=Modes |= CharMode(sPW.charCodeAt(i));javascript
爲了方便往後翻閱,在此處作個學習記錄。html
代碼附上:java
<body> <script type="text/javascript"> //CharMode 函數 function CharMode(iN) { if (iN >= 48 && iN <= 57) //數字 return 1; if (iN >= 65 && iN <= 90) //大寫字母 return 2; if (iN >= 97 && iN <= 122) //小寫 return 4; else return 8; //特殊字符 } //bitTotal 函數 function bitTotal(num) { modes = 0; for (i = 0; i < 4; i++) { if (num & 1) modes++; num >>>= 1; } return modes; } //checkStrong 函數 function checkStrong(sPW) { if (sPW.length <= 4) return 0; //密碼過短 Modes = 0; for (i = 0; i < sPW.length; i++) { Modes |= CharMode(sPW.charCodeAt(i)); } return bitTotal(Modes); } //pwStrength 函數 function pwStrength(pwd) { O_color = "#eeeeee"; L_color = "#FF0000"; M_color = "#FF9900"; H_color = "#33CC00"; if (pwd == null || pwd == '') { Lcolor = Mcolor = Hcolor = O_color; } else { S_level = checkStrong(pwd); switch (S_level) { case 0: Lcolor = Mcolor = Hcolor = O_color; break; case 1: Lcolor = L_color; Mcolor = Hcolor = O_color; break; case 2: Lcolor = Mcolor = M_color; Hcolor = O_color; break; default: Lcolor = Mcolor = Hcolor = H_color; } document.getElementById("strength_L").style.background = Lcolor; document.getElementById("strength_M").style.background = Mcolor; document.getElementById("strength_H").style.background = Hcolor; return; } } </script> <form name="form1" action=""> 輸入密碼:<input type="password" size="10" onkeyup="pwStrength(this.value)" onblur="pwStrength(this.value)"> <br> 密碼強度: <table width="217" border="1" cellspacing="0" cellpadding="1" bordercolor="#cccccc" height="23" style='display: inline'> <tr align="center" bgcolor="#eeeeee"> <td width="33%" id="strength_L"> 弱 </td> <td width="33%" id="strength_M"> 中 </td> <td width="33%" id="strength_H"> 強 </td> </tr> </table> </form> </body>
位運算符是在數字底層(即表示數字的 32 個數位)進行操做的。函數
ECMAScript 整數有兩種類型,即有符號整數(容許用正數和負數)和無符號整數(只容許用正數)。在 ECMAScript 中,全部整數字面量默認都是有符號整數,這意味着什麼呢?學習
有符號整數使用 31 位表示整數的數值,用第 32 位表示整數的符號,0 表示正數,1 表示負數。數值範圍從 -2147483648 到 2147483647。this
能夠以兩種不一樣的方式存儲二進制形式的有符號整數,一種用於存儲正數,一種用於存儲負數。正數是以真二進制形式存儲的,前 31 位中的每一位都表示 2 的冪,從第 1 位(位 0)開始,表示 20,第 2 位(位 1)表示 21。沒用到的位用 0 填充,即忽略不計。例如,下圖展現的是數 18 的表示法。spa
18 的二進制版本只用了前 5 位,它們是這個數字的有效位。把數字轉換成二進制字符串,就能看到有效位:設計
var iNum = 18; alert(iNum.toString(2)); //輸出 "10010"
這段代碼只輸出 "10010",而不是 18 的 32 位表示。其餘的數位並不重要,由於僅使用前 5 位便可肯定這個十進制數值。以下圖所示:code
負數也存儲爲二進制代碼,不過採用的形式是二進制補碼。計算數字二進制補碼的步驟有三步:orm
要肯定 -18 的二進制表示,首先必須獲得 18 的二進制表示,以下所示:
0000 0000 0000 0000 0000 0000 0001 0010
接下來,計算二進制反碼,以下所示:
1111 1111 1111 1111 1111 1111 1110 1101
最後,在二進制反碼上加 1,以下所示:
1111 1111 1111 1111 1111 1111 1110 1101 1 --------------------------------------- 1111 1111 1111 1111 1111 1111 1110 1110
所以,-18 的二進制表示即 1111 1111 1111 1111 1111 1111 1110 1110。記住,在處理有符號整數時,開發者不能訪問 31 位。
有趣的是,把負整數轉換成二進制字符串後,ECMAScript 並不以二進制補碼的形式顯示,而是用數字絕對值的標準二進制代碼前面加負號的形式輸出。例如:
var iNum = -18; alert(iNum.toString(2)); //輸出 "-10010"
這段代碼輸出的是 "-10010",而非二進制補碼,這是爲避免訪問位 31。爲了簡便,ECMAScript 用一種簡單的方式處理整數,使得開發者沒必要關心它們的用法。
另外一方面,無符號整數把最後一位做爲另外一個數位處理。在這種模式中,第 32 位不表示數字的符號,而是值 231。因爲這個額外的位,無符號整數的數值範圍爲 0 到 4294967295。對於小於 2147483647 的整數來講,無符號整數看來與有符號整數同樣,而大於 2147483647 的整數則要使用位 31(在有符號整數中,這一位老是 0)。
把無符號整數轉換成字符串後,只返回它們的有效位。
注意:全部整數字面量都默認存儲爲有符號整數。只有 ECMAScript 的位運算符才能建立無符號整數。
位運算 NOT 由否認號(~)表示,它是 ECMAScript 中爲數很少的與二進制算術有關的運算符之一。
位運算 NOT 是三步的處理過程:
例如:
var iNum1 = 25; //25 等於 00000000000000000000000000011001 //轉換爲 11111111111111111111111111100110 alert(iNum2); //輸出 "-26" var iNum2 = ~iNum1;
位運算 NOT 實質上是對數字求負,而後減 1,所以 25 變 -26。用下面的方法也能夠獲得一樣的方法:
var iNum1 = 25; var iNum2 = -iNum1 -1; alert(iNum2); //輸出 -26
位運算 AND 由和號(&)表示,直接對數字的二進制形式進行運算。它把每一個數字中的數位對齊,而後用下面的規則對同一位置上的兩個數位進行 AND 運算:
第一個數字中的數位 | 第二個數字中的數位 | 結果 |
---|---|---|
1 | 1 | 1 |
1 | 0 | 0 |
0 | 1 | 0 |
0 | 0 | 0 |
例如,要對數字 25 和 3 進行 AND 運算,代碼以下所示:
var iResult = 25 & 3; alert(iResult); //輸出 "1"
25 和 3 進行 AND 運算的結果是 1。爲何?分析以下:
25 = 0000 0000 0000 0000 0000 0000 0001 1001 3 = 0000 0000 0000 0000 0000 0000 0000 0011 --------------------------------------------- AND = 0000 0000 0000 0000 0000 0000 0000 0001
能夠看出,在 25 和 3 中,只有一個數位(位 0)存放的都是 1,所以,其餘數位生成的都是 0,因此結果爲 1。
位運算 OR 由符號(|)表示,也是直接對數字的二進制形式進行運算。在計算每位時,OR 運算符采用下列規則:
第一個數字中的數位 | 第二個數字中的數位 | 結果 |
---|---|---|
1 | 1 | 1 |
1 | 0 | 1 |
0 | 1 | 1 |
0 | 0 | 0 |
仍然使用 AND 運算符所用的例子,對 25 和 3 進行 OR 運算,代碼以下:
var iResult = 25 | 3; alert(iResult); //輸出 "27"
25 和 3 進行 OR 運算的結果是 27:
25 = 0000 0000 0000 0000 0000 0000 0001 1001 3 = 0000 0000 0000 0000 0000 0000 0000 0011 -------------------------------------------- OR = 0000 0000 0000 0000 0000 0000 0001 1011
能夠看出,在兩個數字中,共有 4 個數位存放的是 1,這些數位被傳遞給結果。二進制代碼 11011 等於 27。
位運算 XOR 由符號(^)表示,固然,也是直接對二進制形式進行運算。XOR 不一樣於 OR,當只有一個數位存放的是 1 時,它才返回 1。真值表以下:
第一個數字中的數位 | 第二個數字中的數位 | 結果 |
---|---|---|
1 | 1 | 0 |
1 | 0 | 1 |
0 | 1 | 1 |
0 | 0 | 0 |
對 25 和 3 進行 XOR 運算,代碼以下:
var iResult = 25 ^ 3; alert(iResult); //輸出 "26"
25 和 3 進行 XOR 運算的結果是 26:
25 = 0000 0000 0000 0000 0000 0000 0001 1001 3 = 0000 0000 0000 0000 0000 0000 0000 0011 --------------------------------------------- XOR = 0000 0000 0000 0000 0000 0000 0001 1010
能夠看出,在兩個數字中,共有 4 個數位存放的是 1,這些數位被傳遞給結果。二進制代碼 11010 等於 26。
左移運算由兩個小於號表示(<<)。它把數字中的全部數位向左移動指定的數量。例如,把數字 2(等於二進制中的 10)左移 5 位,結果爲 64(等於二進制中的 1000000):
var iOld = 2; //等於二進制 10 var iNew = iOld << 5; //等於二進制 1000000 十進制 64
注意:在左移數位時,數字右邊多出 5 個空位。左移運算用 0 填充這些空位,使結果成爲完整的 32 位數字。
注意:左移運算保留數字的符號位。例如,若是把 -2 左移 5 位,獲得的是 -64,而不是 64。「符號仍然存儲在第 32 位中嗎?」是的,不過這在 ECMAScript 後臺進行,開發者不能直接訪問第 32 個數位。即便輸出二進制字符串形式的負數,顯示的也是負號形式(例如,-2 將顯示 -10。)
有符號右移運算符由兩個大於號表示(>>)。它把 32 位數字中的全部數位總體右移,同時保留該數的符號(正號或負號)。有符號右移運算符剛好與左移運算相反。例如,把 64 右移 5 位,將變爲 2:
var iOld = 64; //等於二進制 1000000 var iNew = iOld >> 5; //等於二進制 10 十進制 2
一樣,移動數位後會形成空位。此次,空位位於數字的左側,但位於符號位以後。ECMAScript 用符號位的值填充這些空位,建立完整的數字,以下圖所示:
無符號右移運算符由三個大於號(>>>)表示,它將無符號 32 位數的全部數位總體右移。對於正數,無符號右移運算的結果與有符號右移運算同樣。
用有符號右移運算中的例子,把 64 右移 5 位,將變爲 2:
var iOld = 64; //等於二進制 1000000 var iNew = iOld >>> 5; //等於二進制 10 十進制 2
對於負數,狀況就不一樣了。
無符號右移運算用 0 填充全部空位。對於正數,這與有符號右移運算的操做同樣,而負數則被做爲正數來處理。
因爲無符號右移運算的結果是一個 32 位的正數,因此負數的無符號右移運算獲得的老是一個很是大的數字。例如,若是把 -64 右移 5 位,將獲得 134217726。如何獲得這種結果的呢?
要實現這一點,須要把這個數字轉換成無符號的等價形式(儘管該數字自己仍是有符號的),能夠經過如下代碼得到這種形式:
var iUnsigned64 = -64 >>> 0;
而後,用 Number 類型的 toString() 獲取它的真正的位表示,採用的基爲 2:
alert(iUnsigned64.toString(2));
這將生成 11111111111111111111111111000000,即有符號整數 -64 的二進制補碼錶示,不過它等於無符號整數 4294967232。
出於這種緣由,使用無符號右移運算符要當心。