首頁 >web前端 >js教程 >聊聊JavaScript中的7種位元運算符,看看實戰中如何妙用?

聊聊JavaScript中的7種位元運算符,看看實戰中如何妙用?

青灯夜游
青灯夜游轉載
2022-01-06 10:46:372950瀏覽

這篇文章帶大家了解一下JavaScript中的7種位元運算符,看看如何妙用這7種位元運算符,希望對大家有幫助!

聊聊JavaScript中的7種位元運算符,看看實戰中如何妙用?

位元運算子

#運算子用於數值的底層操作,也就是操作記憶體中表示資料的比特(位元)。

ECMAScript 中的所有數值都以IEEE 754 64 位元格式存儲,但位元操作並不會直接應用到64 位元表示,而是先把值轉換為32 位整數,再進行位元操作,之後再把結果轉換為64 位元。

對開發者而言,就好像只有 32 位元整數一樣,因 為 64 位元整數儲存格式是不可見的。既然知道了這些,就只需要考慮 32 位元整數即可。 

有符號整數使用 32 位元的前 31 位元表示整數值。第 32 位元表示數值的符號,如 0 表示正,1 表示負。這 一位稱為符號位(sign bit),它的值決定了數值其餘部分的格式。正值以真正的二進位格式存儲,即 31 位元中的每一位都代表 2 的冪。第一位(稱為第 0 位)表示 20 ,第二位表示 21 ,依此類推。

如果一個位元是空的,則以0填充,相當於忽略不計。例如,數值18的二進位格式為00000000000000000000000000010010, 或更精簡的 10010。後者是用到的 5 個有效位,決定了實際的數值(如下圖)。

聊聊JavaScript中的7種位元運算符,看看實戰中如何妙用?

位元非

#位元非運算子用波浪符(~)表示,它的作用是傳回數值的一補數。位元非是 ECMAScript 中為數 不多的幾個二進位數學運算子之一。看下面的例子:

let num1 = 25; //二进制 00000000000000000000000000011001
let num2 = ~num1; // 二进制 11111111111111111111111111100110
console.log(num2); // -26

這裡,位元非運算子作用到了數值 25,得到的結果是26。由此可以看出,位元非的最終效果是對數值取反並減1,就像執行如下操作的結果一樣:

let num1 = 25;
let num2 = -num1 - 1;
console.log(num2); // "-26"

實際上,儘管兩者返回的結果一樣,但位操作的速度快得多。這是因為位元操作是在數值的底層表示 上完成的。

位元與&

#位元與運算子用和號(&)表示,有兩個操作數。本質上,位元與就是將兩個數的每一個位元對齊, 然後基於真值表中的規則,對每一位執行相應的與操作。

聊聊JavaScript中的7種位元運算符,看看實戰中如何妙用?

以位元與運算在兩個位元都是 1 時傳回 1,在任何一位是 0 時傳回 0。下面看一個例子,我們對數值 25 和 3 求與操作,如下所示:

let result = 25 & 3;
console.log(result); // 1 25 和 3 的按位与操作的结果是 1。

為什麼呢?看下面的二進位計算過程:

聊聊JavaScript中的7種位元運算符,看看實戰中如何妙用?

如如上圖所示,25 和 3 的二進位表示中,只有第 0 位元上的兩個數都是 1。於是結果數值的所有其他位元都 會以 0 填充,因此結果就是 1。

位元或

#位元或運算子用管道符(|)表示,同樣有兩個操作數。按位或遵循以下真值表:

聊聊JavaScript中的7種位元運算符,看看實戰中如何妙用?

按位或運算在至少一位是 1 時傳回 1,兩位都是 0 時傳回 0。仍然以位元與的範例,如果對25 和3 執行位元或,程式碼如下所示:

let result = 25 | 3;
console.log(result); // 27

可見25 和3 的位元或操作的結果是27:

聊聊JavaScript中的7種位元運算符,看看實戰中如何妙用?

#在參與計算的兩個數字中,有4 位元都是1,因此它們直接對應到結果上。二進位碼 11011 等於 27。

以位元異或^

#以位元異或以脫字元(^)表示,同樣有兩個操作數。下面是位元異或的真值表:

聊聊JavaScript中的7種位元運算符,看看實戰中如何妙用?

位元異或與位元或的區別是,它只在一位上是1 的時候回傳1 (兩位都是1 或0,則回傳0)。對數值 25 和 3 執行位元異或運算:

let result = 25 ^ 3;
console.log(result); // 26

可見,25 和 3 的位元異或運算結果為 26,如下所示:

聊聊JavaScript中的7種位元運算符,看看實戰中如何妙用?

#

两个数在 4 位上都是 1,但两个数的第 0 位都是 1,因此那一位在结果中就变成了 0。其余位上的 1 在另一个数上没有对应的 1,因此会直接传递到结果中。二进制码 11010 等于 26。(注意,这比对同样 两个值执行按位或操作得到的结果小 1。)

左移

左移操作符用两个小于号(

let oldValue = 2; // 等于二进制 10
let newValue = oldValue << 5; // 等于二进制 1000000,即十进制 64

注意在移位后,数值右端会空出 5 位。左移会以 0 填充这些空位,让结果是完整的 32 位数值(见下图)。

聊聊JavaScript中的7種位元運算符,看看實戰中如何妙用?

注意,左移会保留它所操作数值的符号。比如,如果-2 左移 5 位,将得到-64,而不是正 64。

有符号右移

有符号右移由两个大于号(>>)表示,会将数值的所有 32 位都向右移,同时保留符号(正或负)。 有符号右移实际上是左移的逆运算。比如,如果将 64 右移 5 位,那就是 2:

let oldValue = 64; // 等于二进制 1000000
let newValue = oldValue >> 5; // 等于二进制 10,即十进制 2

同样,移位后就会出现空位。不过,右移后空位会出现在左侧,且在符号位之后(见图 3-3)。 ECMAScript 会用符号位的值来填充这些空位,以得到完整的数值。

聊聊JavaScript中的7種位元運算符,看看實戰中如何妙用?

无符号右移

无符号右移用 3 个大于号表示(>>>),会将数值的所有 32 位都向右移。对于正数,无符号右移与 有符号右移结果相同。仍然以前面有符号右移的例子为例,64 向右移动 5 位,会变成 2:

let oldValue = 64; // 等于二进制 1000000 
let newValue = oldValue >>> 5; // 等于二进制 10,即十进制 2

对于负数,有时候差异会非常大。与有符号右移不同,无符号右移会给空位补 0,而不管符号位是 什么。对正数来说,这跟有符号右移效果相同。但对负数来说,结果就差太多了。无符号右移操作符将负数的二进制表示当成正数的二进制表示来处理。因为负数是其绝对值的二补数,所以右移之后结果变 得非常之大,如下面的例子所示:

let oldValue = -64; // 等于二进制 11111111111111111111111111000000
let newValue = oldValue >>> 5; // 等于十进制 134217726

在对-64 无符号右移 5 位后,结果是 134 217 726。这是因为-64 的二进制表示是 1111111111111111111 1111111000000,无符号右移却将它当成正值,也就是 4 294 967 232。把这个值右移 5 位后,结果是 00000111111111111111111111111110,即 134 217 726。

实战中的妙用

1.判断奇偶数

// 偶数 & 1 = 0
// 奇数 & 1 = 1
console.log(2 & 1) // 0
console.log(3 & 1) // 1

2. 使用<span style="font-size: 16px;">^</span><span style="font-size: 16px;"></span>来完成值的交换

let a = 2
let b = 5
a ^= b
b ^= a
a ^= b
console.log(a) // 5
console.log(b) // 2

3. 使用<span style="font-size: 16px;">~</span><span style="font-size: 16px;"></span>进行判断

// 常用判断
if (arr.indexOf(item) &gt; -1) {
    // code
}
// 按位非    ~-1 = -(-1) - 1 取反再 -1
if (~arr.indexOf(item)) {
    // code
}

4. 使用&<span style="font-weight: bold; font-size: 16px;"></span><span style="font-family:Microsoft Yahei, Hiragino Sans GB, Helvetica, Helvetica Neue, 微软雅黑, Tahoma, Arial, sans-serif">、</span><strong><span style="font-size: 16px;">|</span></strong><span style="font-size: 16px;"></span>来完成rgb值和16进制颜色值之间的转换

/**
 * 16进制颜色值转RGB
 * @param  {String} hex 16进制颜色字符串
 * @return {String}     RGB颜色字符串
 */
  function hexToRGB(hex) {
    var hexx = hex.replace(&amp;#39;#&amp;#39;, &amp;#39;0x&amp;#39;)
    var r = hexx &gt;&gt; 16
    var g = hexx &gt;&gt; 8 &amp; 0xff
    var b = hexx &amp; 0xff
    return `rgb(${r}, ${g}, ${b})`
}

/**
 * RGB颜色转16进制颜色
 * @param  {String} rgb RGB进制颜色字符串
 * @return {String}     16进制颜色字符串
 */
function RGBToHex(rgb) {
    var rgbArr = rgb.split(/[^\d]+/)
    var color = rgbArr[1]&lt;&lt;16 | rgbArr[2]&lt;&lt;8 | rgbArr[3]
    return &amp;#39;#&amp;#39;+ color.toString(16)
}
// -------------------------------------------------
hexToRGB(&amp;#39;#ffffff&amp;#39;)               // &amp;#39;rgb(255,255,255)&amp;#39;
RGBToHex(&amp;#39;rgb(255,255,255)&amp;#39;)      // &amp;#39;#ffffff&amp;#39;

5. 使用<span style="font-size: 16px;">|</span><span style="font-size: 16px;">~</span><span style="font-size: 16px;"></span>来取整

console.log(~~ 3.1415)    // 3
console.log(3.1415 &gt;&gt; 0)  // 3
console.log(3.1415 &lt;&lt; 0)  // 3
console.log(3.1415 | 0)   // 3
// &gt;&gt;&gt;不可对负数取整
console.log(3.1415 &gt;&gt;&gt; 0)   // 3

【相关推荐:javascript学习教程

以上是聊聊JavaScript中的7種位元運算符,看看實戰中如何妙用?的詳細內容。更多資訊請關注PHP中文網其他相關文章!

陳述:
本文轉載於:juejin.cn。如有侵權,請聯絡admin@php.cn刪除