javascript作為一門高級語言,他盡量讓開發人員減少思考底層的硬件工作原理,而將精力集中在邏輯開發的層面。不過,不論這門語言多么高級,我們必須知道數據依然以bits的形式存儲,有時候我們會直接與這些bits打交道,這就是我們今天的主題——javascript位運算(JavaScript Bit Manipulation)。
在討論之前我們設定一個問題:下面的代碼執行的結果是什么?
var a = "10"| 0 ; console.log("Bitwise Or a is : " +a); var b = "s1132"|0; console.log("Bitwise Or b is : " +b); var c = [1,3,2]&1 ; console.log("Bitwise And c is : " +c); var d = [1]|0; console.log("Bitwise Or d is : " +d); var e = ~function(){}(); console.log("Bitwise Not e is : " +e); var f = ({})|0; console.log("Bitwise Or f is : " +f); var g = ([1])|0; console.log("Bitwise Or g is : " +g); var h = "1ss"^0; console.log("Bitwise Exclusive Or h is : " +h);
同時,希望大家查閱一下四個基本的位運算的原理:and(按位與)、 or(按位或)、 not(按位反) Exclusive Or(亦或) 。
今天我們不分析計算機里面的二進制原理,也不分析4個基本位運算的具體原理。我們分析的重點是在javascript這門語言中,高級的部分與位運算是如何結合的,在javascript中位運算能為我們帶來什么。
一、javascript中的位運算
javascript中的位運算非常復雜,由於javascript試圖創建完全無類型(弱類型)的數據,因此數字以64位浮點值存儲,即雙精度的浮點數。
正如大家所料,javascript中沒有你想使用的Integer(整型)類型。當我們需要用到integer類型時,javascript會內部執行 Toint32方法(瀏覽器內部函數,外部不可調用)將值直接轉化為32位的integer以供調用,並將原值瞬間轉換回雙精度浮點型。
javascript與其他語言的不同之一就是它奇怪的位運算。
何時會用到integer,Toint32方法到底是怎么回事,稍后介紹···
二、javascript位運算符
javascript有一系列位運算符,這里不一一列舉。我們簡單看看下面4個邏輯運算符
And |
& |
Or |
| |
Exclusive Or |
^ |
Not |
~ |
和其他語言一樣,"非"運算符的優先級最高。
類似的運算符 &&,||,!他們只運用在boolean運算中,而不是位運算。
位運算基於數值數據也就是我們剛才提到的"integer"(被從64-bits floating point 經過 Toint32方法轉化而來的32-bits integer),位運算結束后再被轉化成雙精度浮點型。
三、Toint32方法
Toint32我們不能調用,也不好猜測內部的實現邏輯,我們將它的規律總結如下:
1、忽略所有的小數部分
2、如果超出了32位整型能存儲的范圍,結果是1的二進制補碼(即-1)
3、如果是一個小於1的小數,結果是0
4、如果是Infinity(無論正無窮還是負無窮)或者NAN,結果是0
5、如果是true返回1、false返回0
實際上javascript的位運算符並不是最快的,因為他們被限制為32位,而且需要從雙精度浮點型轉換而來並且再轉化回去,盡管如此他們比傳統的操作符要快,因為他們更接近於底層。
下面是和0進行 Or操作的結果,這充分驗證了Toint32函數和位運算的內部原理。
-1.6 | -0 | +0 | 1 | 1.6 | 8 | 16 | 16.8 | 123e-2 | -Infinity | +Infinity | NaN | |
---|---|---|---|---|---|---|---|---|---|---|---|---|
col|0 | -1 | 0 | 0 | 1 | 1 | 8 | 16 | 16 | 1 | 0 | 0 | 0 |
"" | "-1.6" | "0" | "1" | "1.6" | "8" | "16.8" | "123 e-2" |
"010" (Octal) |
"0x10" (Hex) |
"0xFF" (Hex) |
"-010" | "-0x10" | "xx" | |
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
col|0 | 0 | -1 | 0 | 1 | 1 | 8 | 16 | 1 | 10 | 16 | 255 | -10 | 0 | 0 |
undefined | null | true | false | new Object() | function(){ return; } |
|
---|---|---|---|---|---|---|
col|0 | 0 | 0 | 1 | 0 | 0 | 0 |
四、位運算的用途
通過上面的討論,開篇留給讀者思考的問題顯得很簡單,如有問題,請瀏覽討論。下面我們看看位運算的常見用途。
1、替代一些簡單的算數運算
例:24<<2==24*4
32>>3==32/8
2、隨機整數
var ran=Math.random(); alert("a:"+((ran*5)|0));//rang=0-4 alert("a:"+((ran*5)|1));//rang=1-5
3、奇偶判斷
for(var i=0;i<10;i++){ if(i&1){ alert("num is odd!"); } }
4、浮點數取整
if(num>=0){ num|0==Math.floor(num); }else{ num|0==Math.ceil(num); }
位運算的用途建議大家參考 曾少的個人博客http://www.hehe0.com/javascript-wei-yun-suan-xiao-ji/
總結:javascript位運算在我們的日常開發中很少用到,但是深入了解位運算可以幫我們編寫高性能的代碼。由於水平有限,如文中內容有誤歡迎指正。
參考資料:http://www.i-programmer.info/programming/javascript/2550-javascript-bit-manipulation.html
http://jibbering.com/faq/notes/type-conversion/
如需轉載,請說明出處:http://www.cnblogs.com/wisdomoon/p/3338327.html