成人国产在线小视频_日韩寡妇人妻调教在线播放_色成人www永久在线观看_2018国产精品久久_亚洲欧美高清在线30p_亚洲少妇综合一区_黄色在线播放国产_亚洲另类技巧小说校园_国产主播xx日韩_a级毛片在线免费

資訊專欄INFORMATION COLUMN

【譯】 JavaScript中按位操作符的有趣應(yīng)用

oneasp / 2566人閱讀

摘要:檢查設(shè)定位操作符還有一些其他有用的位屏蔽應(yīng)用。請注意,位掩碼中的位將有效地關(guān)閉十進(jìn)制數(shù)中的相應(yīng)位,因?yàn)椤?/p>

原文標(biāo)題:Interesting use cases for JavaScript bitwise operators

原文地址:https://blog.logrocket.com/in...

本文首發(fā)于公眾號:符合預(yù)期的CoyPan

JavaScript提供了幾種運(yùn)算符,可以對一些簡單的值進(jìn)行基本操作,比如算術(shù)操作、賦值操作、邏輯操作、按位操作等。

我們經(jīng)??梢钥吹交旌狭速x值操作,算術(shù)操作和邏輯操作的JavaScript代碼。但是,按位操作的代碼就不是那么常見了。

JavaScript的按位操作符

~按位非

&按位與

|按位或

^按位異或

<<左移

>>有符號右移

>>>無符號右移

在本文中,我們將過一遍所有的按位操作符并且試著理解他們是怎么工作的。同時(shí),我們會編寫簡單的JavaScript的代碼,來看一看一些有趣的按位操作符運(yùn)用。這需要我們了解一下javascript位操作符如何將其操作數(shù)表示為有符號的32位整數(shù)。讓我們開始吧。

按位非(~)

~運(yùn)算符是一元運(yùn)算符;因此,它只需要一個(gè)操作數(shù)。~運(yùn)算符對其操作數(shù)的每一位執(zhí)行NOT操作。非運(yùn)算的結(jié)果稱為補(bǔ)碼。整數(shù)的補(bǔ)碼是通過將整數(shù)的每一位倒轉(zhuǎn)而形成的。

對于給定的整數(shù)(例如170),可以使用~運(yùn)算符計(jì)算補(bǔ)碼,如下所示:

// 170 => 00000000000000000000000010101010
// --------------------------------------
//  ~ 00000000000000000000000010101010
// --------------------------------------
//  = 11111111111111111111111101010101
// --------------------------------------
//  = -171 (decimal)

console.log(~170); // -171

javascript按位運(yùn)算符將其操作數(shù)轉(zhuǎn)換為二進(jìn)制補(bǔ)碼格式的32位有符號整數(shù)。因此,當(dāng)對整數(shù)使用~運(yùn)算符時(shí),得到的值是整數(shù)的補(bǔ)碼。整數(shù)A的補(bǔ)碼的結(jié)果為 - (A+1) 。

~170 => -(170 + 1) => -171

下面是一些需要注意的關(guān)于32位有符號整數(shù)的要點(diǎn),這些整數(shù)由javascript位運(yùn)算符使用:

最有意義(最左邊)的位稱為符號位。正整數(shù)的符號位總是0,負(fù)整數(shù)的符號位總是1。

除符號位之外的其余31位用于表示整數(shù)。因此,可以表示的最大32位整數(shù)是(2^32-1),它是2147483647,而最小整數(shù)是(2^31),它是-2147483648。

對于不在32位有符號整數(shù)范圍內(nèi)的整數(shù),最有效位將被丟棄,直到整數(shù)在該范圍內(nèi)。

以下是一些重要數(shù)字的32位序列表示:

0 => 00000000000000000000000000000000
-1 => 11111111111111111111111111111111
2147483647 => 01111111111111111111111111111111
-2147483648 => 10000000000000000000000000000000

從上面的描述可以很容易得出:

                  ~0 => -1
         ~-1 => 0
 ~2147483647 => -2147483648
~-2147483648 => 2147483647
找到索引

大多數(shù)JavaScript內(nèi)置對象(如數(shù)組和字符串)都有一些有用的方法,可用于檢查數(shù)組中是否存在項(xiàng)或字符串中是否存在子字符串。以下是一些方法:

Array.indexOf()

Array.lastIndexOf()

Array.findIndex()

String.indexOf()

String.lastIndexOf()

String.search()

這些方法都返回某一項(xiàng)或子字符串的從零開始的索引(如果找到);否則,它們返回-1。例如:

const numbers = [1, 3, 5, 7, 9];

console.log(numbers.indexOf(5)); // 2
console.log(numbers.indexOf(8)); // -1

如果我們對么某一項(xiàng)或者子字符串的索引位置不感興趣,我們可以選擇使用布爾值。當(dāng)未找到的項(xiàng)或者子字符串時(shí),返回-1,我們可以認(rèn)為是false,返回其他的值都是true。

function foundIndex (index) {
  return Boolean(~index);
}

在上面的代碼片段中,~運(yùn)算符在-1上使用時(shí)的值為0。使用boolean()將值強(qiáng)制轉(zhuǎn)換為boolean,返回false。對于其他每個(gè)索引值,返回true。因此,以前的代碼段可以修改如下:

const numbers = [1, 3, 5, 7, 9];

console.log(foundIndex(numbers.indexOf(5))); // true
console.log(foundIndex(numbers.indexOf(8))); // false
按位與(&)

& 操作符對其操作數(shù)的每一對對應(yīng)位執(zhí)行一個(gè)和運(yùn)算。& 操作符僅當(dāng)兩個(gè)位都為1時(shí)返回1;否則返回0。因此,與運(yùn)算的結(jié)果等于將每一對對應(yīng)的位相乘。

下面是與操作的可能值:

(0 & 0) === 0     // 0 x 0 = 0
(0 & 1) === 0     // 0 x 1 = 0
(1 & 0) === 0     // 1 x 0 = 0
(1 & 1) === 1     // 1 x 1 = 1
"關(guān)閉"某些位

&操作符通常用于位屏蔽應(yīng)用,以確保為給定的位序列關(guān)閉某些位。這是基于這樣一個(gè)事實(shí),即對于任何位A:

(A & 0 = 0) — 和0進(jìn)行與運(yùn)算,位總是會變成0。

(A & 1 = A) — 和1進(jìn)行與運(yùn)算,位總是保持不變。

舉個(gè)例子,假設(shè)我們有一個(gè)8位的整數(shù),我們希望確保前面的4位被關(guān)閉(置為0)。我們可以用&操作符來實(shí)現(xiàn):

首先,創(chuàng)建一個(gè)位掩碼,其效果是關(guān)閉8位整數(shù)的前4位。該位掩碼將為0B111110000。請注意,位掩碼的前4位設(shè)置為0,而其他每一位設(shè)置為1。

接下來,使用8位整數(shù)和創(chuàng)建的位掩碼進(jìn)行 &操作。

const mask = 0b11110000;

// 222 => 11011110

// (222 & mask)
// ------------
// 11011110
// & 11110000
// ------------
// = 11010000
// ------------
// = 208 (decimal)

console.log(222 & mask); // 208
檢查設(shè)定位

&操作符還有一些其他有用的位屏蔽應(yīng)用。一個(gè)這樣的應(yīng)用是確定給定的位序列是否設(shè)置了一個(gè)或多個(gè)位。例如,假設(shè)我們要檢查是否為給定的十進(jìn)制數(shù)設(shè)置了第五位。以下是我們?nèi)绾问褂?運(yùn)算符來執(zhí)行此操作:

首先,創(chuàng)建一個(gè)位掩碼,用于檢查目標(biāo)位(在本例中為第五位)是否設(shè)置為1。位掩碼上的每個(gè)位都設(shè)置為0,但目標(biāo)位置的位除外,目標(biāo)位置的位設(shè)置為1。二進(jìn)制數(shù)文字可用于輕松實(shí)現(xiàn)這一點(diǎn):

const mask = 0b10000;

接下來,使用十進(jìn)制數(shù)和位掩碼作為操作數(shù)執(zhí)行&操作,并將結(jié)果與位掩碼進(jìn)行比較。如果所有目標(biāo)位都設(shè)置為十進(jìn)制數(shù),&操作的結(jié)果將等于位掩碼。請注意,位掩碼中的0位將有效地關(guān)閉十進(jìn)制數(shù)中的相應(yīng)位,因?yàn)閍&0=0。

// 34 => 100010
// (34 & mask) => (100010 & 010000) = 000000
console.log((34 & mask) === mask); // false

// 50 => 110010
// (50 & mask) => (110010 & 010000) = 010000
console.log((50 & mask) === mask); // true

奇數(shù)或偶數(shù)

使用&運(yùn)算符檢查十進(jìn)制數(shù)的設(shè)定位可以擴(kuò)展到檢查給定的十進(jìn)制數(shù)是偶數(shù)還是奇數(shù)。為了實(shí)現(xiàn)這一點(diǎn),使用1作為位掩碼(以確定是否設(shè)置了第一位或最右邊的位)。

對于整數(shù),可以使用最低有效位(第一位或最右邊的位)來確定數(shù)字是偶數(shù)還是奇數(shù)。如果啟用最低有效位(設(shè)置為1),則數(shù)字為奇數(shù);否則,數(shù)字為偶數(shù)。

function isOdd (int) {
  return (int & 1) === 1;
}

function isEven (int) {
  return (int & 1) === 0;
}

console.log(isOdd(34)); // false
console.log(isOdd(-63)); // true
console.log(isEven(-12)); // true
console.log(isEven(199)); // false
有用的標(biāo)識

在繼續(xù)下一個(gè)運(yùn)算符之前,這里有一些&操作符的有用標(biāo)識(對于任何帶符號的32位整數(shù)A):

(A & 0) === 0
(A & ~A) === 0
(A & A) === A
(A & -1) === A
按位或(|)

運(yùn)算符對其操作數(shù)的每對對應(yīng)位執(zhí)行“或”運(yùn)算。運(yùn)算符僅當(dāng)兩個(gè)位都為0時(shí)返回0;否則返回1。

對于一對位,這里是或操作的可能值:

(0 | 0) === 0
(0 | 1) === 1
(1 | 0) === 1
(1 | 1) === 1
"打開"位

在位屏蔽應(yīng)用中,可以使用運(yùn)算符來確保位序列中的某些位被打開(設(shè)置為1)。這是基于這樣一個(gè)事實(shí):對于任何給定的位A:

(A | 0 = A) — 和0進(jìn)行或運(yùn)算,位總是會保持不變。

(A | 1 = 1) — 和1進(jìn)行或運(yùn)算,位總是為1。

例如,假設(shè)我們有一個(gè)8位整數(shù),我們希望確保所有偶數(shù)位(第二、第四、第六、第八)都打開(設(shè)置為1)。| 運(yùn)算符可用于實(shí)現(xiàn)以下目的:

首先,創(chuàng)建一個(gè)位掩碼,其效果是打開8位整數(shù)的每個(gè)偶數(shù)位。該位掩碼將是0B101010。請注意,位掩碼的偶數(shù)位設(shè)置為1,而其他位設(shè)置為0。

接下來,使用8位整數(shù)和創(chuàng)建的位掩碼執(zhí)行或操作:

const mask = 0b10101010;

// 208 => 11010000

// (208 | mask)
// ------------
// 11010000
// | 10101010
// ------------
// = 11111010
// ------------
// = 250 (decimal)

console.log(208 | mask); // 250
有用的標(biāo)識

在繼續(xù)下一個(gè)運(yùn)算符之前,這里有一些 | 操作符的有用標(biāo)識(對于任何帶符號的32位整數(shù)A):

(A | 0) === A
(A | ~A) === -1
(A | A) === A
(A | -1) === -1
按位異或(^)

^運(yùn)算符對其操作數(shù)的每對對應(yīng)位執(zhí)行異或(異或)運(yùn)算。如果兩個(gè)位相同(0或1),則^運(yùn)算符返回0;否則,它返回1。

對于一對位,下面是可能的值:

(0 ^ 0) === 0
(0 ^ 1) === 1
(1 ^ 0) === 1
(1 ^ 1) === 0
切換位

在位屏蔽應(yīng)用程序中,^ 運(yùn)算符通常用于切換或翻轉(zhuǎn)位序列中的某些位。這是基于這樣一個(gè)事實(shí):對于任何給定的位A:

0進(jìn)行異或運(yùn)算,位總是會保持不變。

(A ^ 0 = A)

當(dāng)與相應(yīng)的1位配對時(shí),該位總是被切換。

(A ^ 1 = 1) — if A is 0
(A ^ 1 = 0) — if A is 1

例如,假設(shè)我們有一個(gè)8位整數(shù),我們希望確保除了最低有效位(第一位)和最高有效位(第八位)之外,每個(gè)位都被切換。可以使用^運(yùn)算符實(shí)現(xiàn)以下目的:

首先,創(chuàng)建一個(gè)位掩碼,其效果是切換8位整數(shù)的每個(gè)位,除了最低有效位和最高有效位。該位掩碼將為0b0111110。請注意,要切換的位設(shè)置為1,而其他位設(shè)置為0。

接下來,使用8位整數(shù)和創(chuàng)建的位掩碼執(zhí)行^操作:

const mask = 0b01111110;

// 208 => 11010000

// (208 ^ mask)
// ------------
// 11010000
// ^ 01111110
// ------------
// = 10101110
// ------------
// = 174 (decimal)

console.log(208 ^ mask); // 174

有用的標(biāo)識

在繼續(xù)下一個(gè)運(yùn)算符之前,以下是^操作的一些有用標(biāo)識(對于任何有符號的32位整數(shù)A):

(A ^ 0) === A
(A ^ ~A) === -1
(A ^ A) === 0
(A ^ -1) === ~A

從上面列出的標(biāo)識中可以明顯看出,-1上的xor操作等同于a上的按位非操作。因此,上面的foundIndex()函數(shù)也可以這樣編寫:

function foundIndex (index) {
  return Boolean(index ^ -1);
}
左移(<<)

左移位(<<)運(yùn)算符接受兩個(gè)操作數(shù)。第一個(gè)操作數(shù)是整數(shù),而第二個(gè)操作數(shù)是要向左移動(dòng)的第一個(gè)操作數(shù)的位數(shù)。零(0)位從右邊移入,而從左邊移入的多余位被丟棄。

例如,考慮整數(shù)170。假設(shè)我們要向左移動(dòng)三位。我們可以使用<<運(yùn)算符,如下所示:

// 170 => 00000000000000000000000010101010

// 170 << 3
// --------------------------------------------
//    (000)00000000000000000000010101010(***)
// --------------------------------------------
//  = (***)00000000000000000000010101010(000)
// --------------------------------------------
//  = 00000000000000000000010101010000
// --------------------------------------------
//  = 1360 (decimal)

console.log(170 << 3); // 1360

左移位位運(yùn)算符(<<)可以使用以下javascript表達(dá)式定義:

(A << B) => A * (2 ** B) => A * Math.pow(2, B)

因此,回顧前面的示例:

(170 << 3) => 170 * (2 ** 3) => 170 * 8 => 1360
顏色轉(zhuǎn)換:RGB到十六進(jìn)制

左移位(<)運(yùn)算符的一個(gè)非常有用的應(yīng)用程序是將顏色從RGB表示轉(zhuǎn)換為十六進(jìn)制表示。

RGB顏色的每個(gè)組件的顏色值在0-255之間。簡單地說,每個(gè)顏色值可以用8位完美地表示。

 0 => 0b00000000 (2進(jìn)制) => 0x00 (16進(jìn)制)
255 => 0b11111111 (2進(jìn)制) => 0xff (16進(jìn)制)

因此,顏色本身可以完美地用24位來表示(紅色、綠色和藍(lán)色分量各8位)。從右邊開始的前8位表示藍(lán)色分量,接下來的8位表示綠色分量,之后的8位表示紅色分量。

(binary) => 11111111 00100011 00010100

   (red) => 11111111 => ff => 255
 (green) => 00100011 => 23 => 35
  (blue) => 00010100 => 14 => 20

   (hex) => ff2314

既然我們已經(jīng)了解了如何將顏色表示為24位序列,那么讓我們來看看如何從顏色的各個(gè)組件的值組成顏色的24位。假設(shè)我們有一個(gè)用RGB(255、35、20)表示的顏色。以下是我們?nèi)绾谓M合這些位:

(red) => 255 => 00000000 00000000 00000000 11111111
(green) =>  35 => 00000000 00000000 00000000 00100011
 (blue) =>  20 => 00000000 00000000 00000000 00010100

// Rearrange the component bits and pad with zeroes as necessary
// Use the left shift operator

  (red << 16) => 00000000 11111111 00000000 00000000
 (green << 8) => 00000000 00000000 00100011 00000000
       (blue) => 00000000 00000000 00000000 00010100

// Combine the component bits together using the OR (|) operator
// ( red << 16 | green << 8 | blue )

      00000000 11111111 00000000 00000000
    | 00000000 00000000 00100011 00000000
    | 00000000 00000000 00000000 00010100
// -----------------------------------------
      00000000 11111111 00100011 00010100
// -----------------------------------------

既然過程非常清楚,下面是一個(gè)簡單的函數(shù),它將顏色的RGB值作為輸入數(shù)組,并基于上述過程返回顏色的相應(yīng)十六進(jìn)制表示:

function rgbToHex ([red = 0, green = 0, blue = 0] = []) {
  return `#${(red << 16 | green << 8 | blue).toString(16)}`;
}
有符號右移(>>)

有符號右移(>>)運(yùn)算符的符號接受兩個(gè)操作數(shù)。第一個(gè)操作數(shù)是整數(shù),而第二個(gè)操作數(shù)是要右移的第一個(gè)操作數(shù)的位數(shù)。

已移到右邊的多余位將被丟棄,而符號位(最左邊的位)的副本將從左邊移入。所以,整數(shù)的符號位會一直保留。所以這種運(yùn)算叫做有符號右移。

例如,考慮整數(shù)170和-170。假設(shè)我們想把三位移到右邊。我們可以使用>>運(yùn)算符,如下所示:

//  170 => 00000000000000000000000010101010
// -170 => 11111111111111111111111101010110

// 170 >> 3
// --------------------------------------------
//    (***)00000000000000000000000010101(010)
// --------------------------------------------
//  = (000)00000000000000000000000010101(***)
// --------------------------------------------
//  = 00000000000000000000000000010101
// --------------------------------------------
//  = 21 (decimal)

// -170 >> 3
// --------------------------------------------
//    (***)11111111111111111111111101010(110)
// --------------------------------------------
//  = (111)11111111111111111111111101010(***)
// --------------------------------------------
//  = 11111111111111111111111111101010
// --------------------------------------------
//  = -22 (decimal)

console.log(170 >> 3); // 21
console.log(-170 >> 3); // -22

通過以下javascript表達(dá)式可以描述有符號右移:

(A >> B) => Math.floor(A / (2 ** B)) => Math.floor(A / Math.pow(2, B))

因此,之前的那個(gè)例子可以如下表示:

(170 >> 3) => Math.floor(170 / (2 ** 3)) => Math.floor(170 / 8) => 21
(-170 >> 3) => Math.floor(-170 / (2 ** 3)) => Math.floor(-170 / 8) => -22
顏色提取

有符號右移(>>)運(yùn)算符的一個(gè)非常好的應(yīng)用是從顏色中提取RGB顏色值。當(dāng)顏色以RGB表示時(shí),很容易區(qū)分紅色、綠色和藍(lán)色顏色分量值。但是,對于以十六進(jìn)制表示的顏色,這將花費(fèi)更多的精力。

在上一節(jié)中,我們看到了從顏色的各個(gè)組成部分(紅色、綠色和藍(lán)色)的位組成顏色的過程。如果我們反向執(zhí)行這個(gè)過程,我們將能夠提取顏色的各個(gè)組成部分的值。讓我們試一試。

假設(shè)我們有一個(gè)用十六進(jìn)制表示法ff2314表示的顏色。下面是顏色的有符號32位表示:

(color) => ff2314 (hexadecimal) => 11111111 00100011 00010100 (binary)

// 32-bit representation of color
00000000 11111111 00100011 00010100

為了獲得單個(gè)部分,我們將根據(jù)需要將顏色位按8的倍數(shù)右移,直到從右邊得到目標(biāo)組件位作為前8位。由于顏色的32位中的符號標(biāo)志位是0,因此我們可以安全地使用符號傳播右移位(>>)運(yùn)算符。

color => 00000000 11111111 00100011 00010100

// Right shift the color bits by multiples of 8
// Until the target component bits are the first 8 bits from the right

  red => color >> 16
      => 00000000 11111111 00100011 00010100 >> 16
      => 00000000 00000000 00000000 11111111

green => color >> 8
      => 00000000 11111111 00100011 00010100 >> 8
      => 00000000 00000000 11111111 00100011

 blue => color >> 0 => color
      => 00000000 11111111 00100011 00010100

現(xiàn)在我們將目標(biāo)顏色位作為右前8位,我們需要一種方法來屏蔽除前8位之外的所有其他位。這使我們回到和(&)運(yùn)算符。請記住,&運(yùn)算符可用于確保關(guān)閉某些位。

讓我們從創(chuàng)建所需的位掩碼開始。就像這樣:

mask => 00000000 00000000 00000000 11111111
     => 0b11111111 (binary)
     => 0xff (hexadecimal)

準(zhǔn)備好位掩碼后,我們可以對上一次右移操作的每個(gè)結(jié)果執(zhí)行與(&)操作,使用位掩碼提取目標(biāo)顏色。

red => color >> 16 & 0xff
      =>   00000000 00000000 00000000 11111111
      => & 00000000 00000000 00000000 11111111
      => = 00000000 00000000 00000000 11111111
      =>   255 (decimal)

green => color >> 8 & 0xff
      =>   00000000 00000000 11111111 00100011
      => & 00000000 00000000 00000000 11111111
      => = 00000000 00000000 00000000 00100011
      =>   35 (decimal)

 blue => color & 0xff
      =>   00000000 11111111 00100011 00010100
      => & 00000000 00000000 00000000 11111111
      => = 00000000 00000000 00000000 00010100
      =>   20 (decimal)

基于上述過程,這里有一個(gè)簡單的函數(shù),它以十六進(jìn)制顏色字符串(帶有六個(gè)十六進(jìn)制數(shù)字)作為輸入,并返回相應(yīng)的RGB顏色分量值數(shù)組。

function hexToRgb (hex) {
  hex = hex.replace(/^#?([0-9a-f]{6})$/i, "$1");
  hex = Number(`0x${hex}`);

  return [
    hex >> 16 & 0xff, // red
    hex >> 8 & 0xff,  // green
    hex & 0xff        // blue
  ];
}
無符號右移(>>>)

無符號右移位(>>>)運(yùn)算符的行為非常類似于符號傳播右移位(>>)運(yùn)算符。然而,關(guān)鍵區(qū)別在于從左邊移入的位。

顧名思義,0位總是從左邊移入。因此,>>運(yùn)算符始終返回?zé)o符號32位整數(shù),因?yàn)榻Y(jié)果整數(shù)的符號位始終為0。對于正整數(shù),>>和>>>都將始終返回相同的結(jié)果。

例如,考慮整數(shù)170和-170。假設(shè)我們要將3位移到右邊,我們可以使用>>>操作符,如下所示:

//  170 => 00000000000000000000000010101010
// -170 => 11111111111111111111111101010110

// 170 >>> 3
// --------------------------------------------
//    (***)00000000000000000000000010101(010)
// --------------------------------------------
//  = (000)00000000000000000000000010101(***)
// --------------------------------------------
//  = 00000000000000000000000000010101
// --------------------------------------------
//  = 21 (decimal)

// -170 >>> 3
// --------------------------------------------
//    (***)11111111111111111111111101010(110)
// --------------------------------------------
//  = (000)11111111111111111111111101010(***)
// --------------------------------------------
//  = 00011111111111111111111111101010
// --------------------------------------------
//  = 536870890 (decimal)

console.log(170 >>> 3); // 21
console.log(-170 >>> 3); // 536870890
配置標(biāo)志

在總結(jié)本教程之前,讓我們考慮另一個(gè)非常常見的位操作符和位屏蔽應(yīng)用:配置標(biāo)志。

假設(shè)我們有一個(gè)函數(shù),它接受幾個(gè)布爾選項(xiàng),這些選項(xiàng)可以用來控制函數(shù)的運(yùn)行方式或返回的值的類型。創(chuàng)建此函數(shù)的一種可能方法是將所有選項(xiàng)作為參數(shù)傳遞給該函數(shù),可能使用一些默認(rèn)值,例如:

function doSomething (optA = true, optB = true, optC = false, optD = true, ...) {
  // something happens here...
}

當(dāng)然,這不太方便。在以下兩種情況下,這種方法開始變得相當(dāng)有問題:

假設(shè)我們有10個(gè)以上的布爾選項(xiàng)。我們不能用這么多參數(shù)定義函數(shù)。

假設(shè)我們只想為第五個(gè)和第九個(gè)選項(xiàng)指定一個(gè)不同的值,并讓其他選項(xiàng)保留默認(rèn)值。我們需要調(diào)用函數(shù),將默認(rèn)值作為所有其他選項(xiàng)的參數(shù)傳遞,同時(shí)為第五個(gè)和第九個(gè)選項(xiàng)傳遞所需的值。

用前面的方法解決問題的一種方法是為配置選項(xiàng)使用一個(gè)對象,如下所示:

const defaultOptions = {
  optA: true,
  optB: true,
  optC: false,
  optD: true,
  ...
};

function doSomething (options = defaultOptions) {
  // something happens here...
}

這種方法非常優(yōu)雅,您很可能已經(jīng)看到它被使用了,甚至自己在某個(gè)地方使用過。然而,使用這種方法時(shí),options參數(shù)將始終是一個(gè)對象,對于配置選項(xiàng)來說,這可以被認(rèn)為是多余的。

如果所有選項(xiàng)都采用布爾值,則可以使用整數(shù)而不是對象來表示選項(xiàng)。在這種情況下,整數(shù)的某些位將映射到指定的選項(xiàng)。如果某個(gè)位被打開(設(shè)置為1),則指定選項(xiàng)的值為“真”;否則為“假”。

我們可以用一個(gè)簡單的例子來演示這種方法。假設(shè)我們有一個(gè)函數(shù),它規(guī)范化包含數(shù)字的數(shù)組列表中的項(xiàng),并返回規(guī)范化的數(shù)組。返回的數(shù)組可以由三個(gè)選項(xiàng)控制,即:

fraction:將數(shù)組中的每個(gè)項(xiàng)除以數(shù)組中的最大項(xiàng)

unique:從數(shù)組中刪除重復(fù)項(xiàng)

sorted:將數(shù)組中的項(xiàng)從最低到最高排序

我們可以使用一個(gè)3位整數(shù)來表示這些選項(xiàng),每個(gè)位都映射到一個(gè)選項(xiàng)。以下代碼段顯示選項(xiàng)標(biāo)志:

const LIST_FRACTION = 0x1; // (001)
const LIST_UNIQUE = 0x2;   // (010)
const LIST_SORTED = 0x4;   // (100)

要激活一個(gè)或多個(gè)選項(xiàng),可以根據(jù)需要使用運(yùn)算符組合相應(yīng)的標(biāo)志。例如,我們可以創(chuàng)建一個(gè)標(biāo)志來激活所有選項(xiàng),如下所示:

const LIST_ALL = LIST_FRACTION | LIST_UNIQUE | LIST_SORTED; // (111)

同樣,假設(shè)我們只希望默認(rèn)情況下激活fraction和sorted選項(xiàng)。我們可以再次使用運(yùn)算符,如下所示:

const LIST_DEFAULT = LIST_FRACTION | LIST_SORTED; // (101)

雖然只使用三個(gè)選項(xiàng)看起來并不糟糕,但當(dāng)有這么多選項(xiàng)時(shí),它往往會變得非?;靵y,并且默認(rèn)情況下需要激活其中的許多選項(xiàng)。在這種情況下,更好的方法是使用^運(yùn)算符停用不需要的選項(xiàng):

const LIST_DEFAULT = LIST_ALL ^ LIST_UNIQUE; // (101)

這里,我們有一個(gè)列表“所有”標(biāo)志,可以激活所有選項(xiàng)。然后,我們使用^運(yùn)算符停用唯一選項(xiàng),并根據(jù)需要保留其他選項(xiàng)。

現(xiàn)在我們已經(jīng)準(zhǔn)備好了選項(xiàng)標(biāo)志,可以繼續(xù)定義normalizelist()函數(shù):

function normalizeList (list, flag = LIST_DEFAULT) {
  if (flag & LIST_FRACTION) {
    const max = Math.max(...list);
    list = list.map(value => Number((value / max).toFixed(2)));
  }
  if (flag & LIST_UNIQUE) {
    list = [...new Set(list)];
  }
  if (flag & LIST_SORTED) {
    list = list.sort((a, b) => a - b);
  }
  return list;
}

為了檢查某個(gè)選項(xiàng)是否被激活,我們使用&運(yùn)算符來檢查該選項(xiàng)的相應(yīng)位是否被打開(設(shè)置為1)。&操作是通過傳遞給函數(shù)的flag參數(shù)和選項(xiàng)的對應(yīng)標(biāo)志來執(zhí)行的,如下面的代碼段所示:

// Checking if the unique option is activated
// (flag & LIST_UNIQUE) === LIST_UNIQUE (activated)
// (flag & LIST_UNIQUE) === 0 (deactivated)

flag & LIST_UNIQUE
總結(jié)

嘿,我真的很高興你能讀完這篇文章,盡管讀了很長時(shí)間,但我強(qiáng)烈希望你在讀的時(shí)候?qū)W到一兩件事。謝謝你的時(shí)間。

正如我們在本文中所看到的,雖然使用得很謹(jǐn)慎,但javascript的位操作符有一些非常有趣的用例。我強(qiáng)烈希望您在閱讀本文的過程中獲得的見解從現(xiàn)在起用在你的日常開發(fā)中。

文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。

轉(zhuǎn)載請注明本文地址:http://systransis.cn/yun/110056.html

相關(guān)文章

  • 】11 種在大多數(shù)教程中找不到JavaScript技巧

    摘要:否則,將返回空數(shù)組的長度。該提案目前處于第階段,作為一項(xiàng)實(shí)驗(yàn)性功能。轉(zhuǎn)換為布爾值除了常規(guī)的布爾值和之外,還將所有其他值視為或。這也可以用于將布爾值轉(zhuǎn)換為數(shù)字,如下所示在某些上下文中,將被解釋為連接操作符,而不是加法操作符。 譯者:前端小智 原文:medium.com/@bretcamero… 當(dāng)我開始學(xué)習(xí)JavaScript時(shí),我把我在別人的代碼、code challenge網(wǎng)站以及我使用...

    EastWoodYang 評論0 收藏0
  • 由left-pad扯到JS中位運(yùn)算

    摘要:原碼補(bǔ)碼和反碼原碼一個(gè)數(shù)在計(jì)算機(jī)中是以二進(jìn)制的形式存在的,其中第一位存放符號正數(shù)為負(fù)數(shù)為。中的位運(yùn)算在中按位操作符會將其操作數(shù)轉(zhuǎn)成補(bǔ)碼形式的有符號位整數(shù)。原文鏈接由扯到中的位運(yùn)算 這個(gè)話題的由來是2016年3月份的時(shí)候 NPM 社區(qū)發(fā)生了‘left-pad’事件,不久后社區(qū)就有人發(fā)布了用來補(bǔ)救的,也是現(xiàn)在大家能用到的 left-pad 庫。 最開始這個(gè)庫的代碼是這樣的。 module....

    LeoHsiun 評論0 收藏0
  • 2021-09-08 交換兩個(gè)變量

    摘要:千里之行始于足下題目交換兩個(gè)變量不允許使用臨時(shí)變量思路首先大家一定需要深入了解在語言中按位異或操作符的作用,不懂的建議大家去百度。 千里之行始于足下 題目: 交...

    wangshijun 評論0 收藏0
  • 有趣JavaScript原生數(shù)組函數(shù)

    摘要:對的描述如下將會給數(shù)組里的每一個(gè)元素執(zhí)行一遍回調(diào)函數(shù),直到回調(diào)函數(shù)返回。的運(yùn)行原理和類似,但回調(diào)函數(shù)是返回而不是?;卣{(diào)函數(shù)只會對已經(jīng)指定值的數(shù)組項(xiàng)調(diào)用。 showImg(http://fw008950-flywheel.netdna-ssl.com/wp-content/uploads/2013/11/JavaScript_Array_Functions_Header.jpg); 在...

    oliverhuang 評論0 收藏0

發(fā)表評論

0條評論

最新活動(dòng)
閱讀需要支付1元查看
<