Javascript中的位運算符

本文章主要講解JS中位運算符的基本說明和常見用法

位運算符用于32位的數(shù)字上, 任何的數(shù)字操作都將轉(zhuǎn)為32位, 運算結(jié)果再轉(zhuǎn)化為JS數(shù)字

js包括以下位運算符

  • '&': AND運算符
  • '|': OR運算符
  • '~': 取反
  • '^': 異或
  • '<<': 左移
  • '>>': 右移

下面一一介紹

AND運算符'&' -- 按位與

按位與運算符"&"是雙目運算符少态。 其功能是將參與運算的兩數(shù)轉(zhuǎn)成32位二進制后, 各對應(yīng)的二進位相與。只有對應(yīng)的兩個二進位均為1時易遣,結(jié)果位才為1 彼妻,否則為0。
例如:

console.log(6&2); //輸出2
console.log(10&5); //輸出0

說明(下述文字中的二進制, 前面(28位)均為0, 所以省略了)

  • 6的二進制位0110, 2的二進制位0010, 結(jié)果就是0010, 轉(zhuǎn)成十進制也就是2
  • 10的二進制位為1010, 5的二進制位0101, 所以結(jié)果為0000, 也就是0

這個運算符, 我一般用它來獲取RGB顏色值中的藍色, 例如:

var rgbStr = "#6abc3a";
//將字符串轉(zhuǎn)成十進制整數(shù)
var rgb = parseInt(rgbStr.replace(/^\s*#|\s*$/g, ""), 16);
//獲取顏色值中的藍色
var b = rgb&0xff;
//輸出藍色值得16進制字符串
console.log(b.toString(16));//輸出: 3a

OR運算符'|' -- 按位或

按位或運算符“|”是雙目運算符。 其功能是將參與運算的兩數(shù)轉(zhuǎn)成32位二進制后, 各對應(yīng)的二進位相或侨歉。只要對應(yīng)的二個二進位有一個為1時屋摇,結(jié)果位就為1。
例如:

console.log(6 | 2); //輸出6
console.log(10 | 5); //輸出15

說明(下述文字中的二進制, 前面(28位)均為0, 所以省略了)

  • 6的二進制位0110, 2的二進制位0010, 結(jié)果就是0110, 轉(zhuǎn)成十進制也就是6
  • 10的二進制位為1010, 5的二進制位0101, 所以結(jié)果為1111, 也就是15

這個運算符可以用來對數(shù)值進行取證, 用起來應(yīng)該比Math.floor和Math.ceil方便, 實例如下

console.log(10.5 | 0);
console.log(10.3 | 0);
console.log(10.8 | 0);

以上的輸出結(jié)果都是10

注意: 無論正數(shù)還是負數(shù), 此方法只是刪除數(shù)字的小數(shù)部分, 所以

  • 對正數(shù), 其運行的結(jié)果和Math.floor是一樣的;
  • 對負數(shù), 其運行結(jié)果和Math.ceil是一樣的

下面是個例子

console.log(8.35 | 0); //輸出: 8
console.log(Math.floor(8.35)); //輸出: 8
console.log(Math.ceil(8.35)); //輸出: 9

console.log(-8.35 | 0); //輸出: -8
console.log(Math.floor(-8.35)); //輸出: -9
console.log(Math.ceil(-8.35)); //輸出: -8

取反運算符'~'

取反運算符為單目運算符幽邓,具有右結(jié)合性摊册。 其功能是對參與運算的數(shù)的各二進位按位取反

下面也舉一個例子

console.log(~2); //輸出-3
console.log(~5); //輸出-6

這里解說有點麻煩, 需要將所有的32位都列出來, 所以就不加說明了

: 到目前為止, 我沒有在編程里面用到此運算符

異或運算符'^' -- 按位異或

按位異或運算符“^”是雙目運算符。 其功能是參與運算的兩數(shù)各對應(yīng)的二進位相異或颊艳,當兩對應(yīng)的二進位相異(即對應(yīng)位數(shù)值不相同, 也就是其中一個為1,另一個為0)時,結(jié)果為1忘分。

例如

console.log(6 ^ 2); //輸出4
console.log(10 ^ 5); //輸出15

說明(下述文字中的二進制, 前面(28位)均為0, 所以省略了)

  • 6的二進制位0110, 2的二進制位0010, 結(jié)果就是0100, 轉(zhuǎn)成十進制也就是4
  • 10的二進制位為1010, 5的二進制位0101, 所以結(jié)果為1111, 也就是15

此運算符可以用來交換兩個整型變量的值(不定義中間變量)

var a = 125, b = 10;
a = a ^ b;
b = a ^ b;
a = a ^ b;
console.log("a = "+ a + ", b = " + b); 
//輸出: a = 10, b = 125

另外也可以判斷兩個整數(shù)是否相等, 如下

a ^ b == 0; //如果a,b相等, 為true, 否則為false

右移運算符'>>'

右移運算符“>>”是雙目運算符, 其功能是把“>>”左邊的運算數(shù)的各二進位全部右移若干位(不足位補0)棋枕,“>>”右邊的數(shù)指定移動的位數(shù)。
右移n位的結(jié)果相當于整除2的n次方后的值
例如

console.log(6>>2); //輸出: 1
console.log(10>>2); //輸出: 2

說明(下述文字中的二進制, 前面(28位)均為0, 所以省略了)

  • 6的二進制位0110, 向右移兩位, 結(jié)果就是0001, 轉(zhuǎn)成十進制也就是1
  • 10的二進制位為1010, 向右移兩位, 所以結(jié)果為0010, 也就是2

說明一下
m >> n, 相當于m / (2^n)[ 這里的^不是異或運算符, 而是2的n次方 ], 轉(zhuǎn)成js表達式就是Math.floor(m / Math.pow(2, n));

console.log(100>>4); //輸出: 6
console.log(Math.floor(100 / Math.pow(2,4)));  //輸出: 6
console.log(120>>3); //輸出: 15
console.log(Math.floor(120 / Math.pow(2,3)));  //輸出: 15

目前我主要用于RGB顏色值中R(紅色)的分離, 并配合按位與'&'運算符, 可以分離出G(綠色)
完整分離RGB顏色的代碼如下

var rgbStr = "#6abc3a";
//將字符串轉(zhuǎn)成十進制整數(shù)
var rgb = parseInt(rgbStr.replace(/^\s*#|\s*$/g, ""), 16);
//獲取顏色值中的藍色
var b = rgb&0xff;
var g = rgb>>8&0xff;
var r = rgb>>16;
//輸出RGB/R/G/G色值的16進制字符串
console.log("rgb = " + rgb.toString(16));//輸出: 6abc3a
console.log("r = " + r.toString(16));//輸出: 6a
console.log("g = " + g.toString(16));//輸出: bc
console.log("b = " + b.toString(16));//輸出: 3a
//下面可以分別對R/G/B值進行計算, 如下(將顏色值變亮)
r = Math.min(r*1.3, 255);
g = Math.min(g*1.3, 255);
b = Math.min(b*1.3, 255);
//最后在將各個分量組合(要用到左移運算符)在一起, 就可以應(yīng)用了

也可以用來對數(shù)值取整, 方法/結(jié)果和'|'是一樣的

左移運算符 '<<'

左移運算符“<<”是雙目運算符妒峦。左移n位就是乘以2的n次方重斑。 其功能把“<<”左邊的運算數(shù)的各二進位全部左移若干位,由“<<”右邊的數(shù)指定移動的位數(shù)肯骇,高位丟棄窥浪,低位補0

例如

console.log(6<<2); //相當于6*(2*2), 輸出: 24
console.log(10<<3); //相當于10*(2*2*2), 輸出: 80

我常用于顏色分量的合成, 接著上述右移運算符的顏色例子

var newRGB = (r<<16)+(r<<8)+(g)
//或者可以用按位或 '|'
//var newRGB = (r<<16)|(r<<8)|(g)

下面是一個顏色值的完整例子

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8">
    <title></title>
    <style>
      .container{ width: 250px;text-align: center; margin: 0 auto;}
      #rect{ width: 120px; height: 65px; background-color: #68a28b; margin: 10px auto;}
      button{margin-right: 20px;}
    </style>
  </head>
  <body>
    <div class="container">
      <div id="rect"></div>
      <button id="light">加亮</button>
      <button id="reset">重置</button>
      <button id="dark">變暗</button>
    </div>
    <script>
      var rect = document.getElementById("rect");
      var light = document.getElementById("light");
      var reset = document.getElementById("reset");
      var dark = document.getElementById("dark");

      var initColor = "#68a28b";
      var newColor = initColor;
      light.addEventListener("click", function (){
        ld(1.1, Math.min, 255);
      });
      dark.addEventListener("click", function (){
        ld(0.9, Math.max, 0);
      });
      reset.addEventListener("click", function (){
        newColor = initColor;
        rect.style.backgroundColor = newColor;
      });
      function ld(factor, func, mom){
        var obj = fl(newColor);
        console.log(obj);
        obj.r = func(obj.r*factor, mom)|0;
        obj.g = func(obj.g*factor,mom)|0;
        obj.b = func(obj.b*factor, mom)|0;
        console.log(obj);
        newColor = "#" + hc(obj).toString(16);
        rect.style.backgroundColor = newColor;
      }
      //分離R/G/B
      function fl(rgb){
        if(rgb.constructor == String)
          rgb = parseInt(rgb.replace(/^\s*#|\s*$/g, ""), 16);
        var obj = {};
        obj.r = rgb>>16;
        obj.g = rgb>>8&0xff;
        obj.b = rgb&0xff;

        return obj;
      }
      //合并RGB
      function hc(obj){
        return (obj.r<<16)|(obj.g<<8)|(obj.b);
      }
    </script>
  </body>
</html>
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市笛丙,隨后出現(xiàn)的幾起案子漾脂,更是在濱河造成了極大的恐慌,老刑警劉巖胚鸯,帶你破解...
    沈念sama閱讀 216,372評論 6 498
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件骨稿,死亡現(xiàn)場離奇詭異,居然都是意外死亡姜钳,警方通過查閱死者的電腦和手機坦冠,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,368評論 3 392
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來哥桥,“玉大人辙浑,你說我怎么就攤上這事∧飧猓” “怎么了判呕?”我有些...
    開封第一講書人閱讀 162,415評論 0 353
  • 文/不壞的土叔 我叫張陵,是天一觀的道長已卸。 經(jīng)常有香客問我佛玄,道長,這世上最難降的妖魔是什么累澡? 我笑而不...
    開封第一講書人閱讀 58,157評論 1 292
  • 正文 為了忘掉前任梦抢,我火速辦了婚禮,結(jié)果婚禮上愧哟,老公的妹妹穿的比我還像新娘奥吩。我一直安慰自己哼蛆,他們只是感情好,可當我...
    茶點故事閱讀 67,171評論 6 388
  • 文/花漫 我一把揭開白布霞赫。 她就那樣靜靜地躺著腮介,像睡著了一般。 火紅的嫁衣襯著肌膚如雪端衰。 梳的紋絲不亂的頭發(fā)上叠洗,一...
    開封第一講書人閱讀 51,125評論 1 297
  • 那天,我揣著相機與錄音旅东,去河邊找鬼灭抑。 笑死,一個胖子當著我的面吹牛抵代,可吹牛的內(nèi)容都是我干的腾节。 我是一名探鬼主播,決...
    沈念sama閱讀 40,028評論 3 417
  • 文/蒼蘭香墨 我猛地睜開眼荤牍,長吁一口氣:“原來是場噩夢啊……” “哼案腺!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起康吵,我...
    開封第一講書人閱讀 38,887評論 0 274
  • 序言:老撾萬榮一對情侶失蹤劈榨,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后涎才,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體鞋既,經(jīng)...
    沈念sama閱讀 45,310評論 1 310
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,533評論 2 332
  • 正文 我和宋清朗相戀三年耍铜,在試婚紗的時候發(fā)現(xiàn)自己被綠了邑闺。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 39,690評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡棕兼,死狀恐怖陡舅,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情伴挚,我是刑警寧澤靶衍,帶...
    沈念sama閱讀 35,411評論 5 343
  • 正文 年R本政府宣布,位于F島的核電站茎芋,受9級特大地震影響颅眶,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜田弥,卻給世界環(huán)境...
    茶點故事閱讀 41,004評論 3 325
  • 文/蒙蒙 一涛酗、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦商叹、人聲如沸燕刻。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,659評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽卵洗。三九已至,卻和暖如春弥咪,著一層夾襖步出監(jiān)牢的瞬間过蹂,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 32,812評論 1 268
  • 我被黑心中介騙來泰國打工聚至, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留榴啸,地道東北人。 一個月前我還...
    沈念sama閱讀 47,693評論 2 368
  • 正文 我出身青樓晚岭,卻偏偏與公主長得像,于是被迫代替她去往敵國和親勋功。 傳聞我的和親對象是個殘疾皇子坦报,可洞房花燭夜當晚...
    茶點故事閱讀 44,577評論 2 353

推薦閱讀更多精彩內(nèi)容