Gdzie mogę użyć operatora bitowego w JavaScript?

Przeczytałem ' Czym są operatory bitowe?', więc wiem co operatory bitowe są, ale nadal Nie wiem, jak można ich używać. Czy ktoś może podać jakieś rzeczywiste przykłady, gdzie operator bitowy byłby przydatny w JavaScript?

Dzięki.

Edit:

Po prostu kopanie w źródło jQuery znalazłem kilka miejsc, gdzie operatory bitowe są używane, na przykład: (tylko operator&)

// Line 2756:
event.which = (event.button & 1 ? 1 : ( event.button & 2 ? 3 : ( event.button & 4 ? 2 : 0 ) ));

// Line 2101
var ret = a.compareDocumentPosition(b) & 4 ? -1 : a === b ? 0 : 1;
Author: mikemaccana, 2009-03-17

16 answers

Przykład:

Parsuje wartość szesnastkową, aby uzyskać wartości kolorów RGB.

var hex = 'ffaadd';
var rgb = parseInt(hex, 16); // rgb is 16755421


var red   = (rgb >> 16) & 0xFF; // returns 255
var green = (rgb >> 8) & 0xFF;  // 170
var blue  = rgb & 0xFF;     // 221  
 57
Author: Mark,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-05-09 17:20:42

I mocno używają operatorów bitowych do konwersji numerycznych w skryptach produkcyjnych, ponieważ czasami są one znacznie szybsze niż ich odpowiedniki Math lub parseInt.

Cena jaką muszę zapłacić to czytelność kodu. Więc zwykle używam Math w rozwoju i bitwise w produkcji.

Możesz znaleźć kilka sztuczek wydajności na jsperf.com .

Jak widać, przeglądarki nie optymalizują Math.ceil I parseInt przez lata, więc przewiduję, że bitowe będą szybszy i krótszy sposób robienia rzeczy również w furure .

Dalsze informacje o SO...


Bonus: Ściągawka dla | 0: Łatwy i szybki sposób na konwersję czegokolwiek na liczbę całkowitą:

( 3|0 ) === 3;             // it does not change integers
( 3.3|0 ) === 3;           // it casts off the fractional part in fractionalal numbers
( 3.8|0 ) === 3;           // it does not round, but exactly casts off the fractional part
( -3.3|0 ) === -3;         // including negative fractional numbers
( -3.8|0 ) === -3;         // which have Math.floor(-3.3) == Math.floor(-3.8) == -4
( "3"|0 ) === 3;           // strings with numbers are typecast to integers
( "3.8"|0 ) === 3;         // during this the fractional part is cast off too
( "-3.8"|0 ) === -3;       // including negative fractional numbers
( NaN|0 ) === 0;           // NaN is typecast to 0
( Infinity|0 ) === 0;      // the typecast to 0 occurs with the Infinity
( -Infinity|0 ) === 0;     // and with -Infinity
( null|0 ) === 0;          // and with null,
( (void 0)|0 ) === 0;      // and with undefined
( []|0 ) === 0;            // and with an empty array
( [3]|0 ) === 3;           // but an array with one number is typecast to number
( [-3.8]|0 ) === -3;       // including the cast off of the fractional part
( [" -3.8 "]|0 ) === -3;   // including the typecast of strings to numbers
( [-3.8, 22]|0 ) === 0     // but an Array with several numbers is typecast to 0
( {}|0 ) === 0;                // an empty object is typecast to 0
( {'2':'3'}|0 ) === 0;         // or a not empty object
( (function(){})|0 ) === 0;    // an empty function is typecast to 0 too
( (function(){ return 3;})|0 ) === 0;

I trochę magii dla mnie:

3 | '0px' === 3;
 38
Author: Dan,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-05-23 12:34:32

W JavaScript można użyć negacji dwukierunkowej (~~n) jako zamiennika dla Math.floor(n) (Jeśli n jest liczbą dodatnią) lub parseInt(n, 10) (nawet jeśli n jest liczbą ujemną). n|n i n&n zawsze dają te same wyniki co ~~n.

var n = Math.PI;
n; // 3.141592653589793
Math.floor(n); // 3
parseInt(n, 10); // 3
~~n; // 3
n|n; // 3
n&n; // 3

// ~~n works as a replacement for parseInt() with negative numbers…
~~(-n); // -3
(-n)|(-n); // -3
(-n)&(-n); // -3
parseInt(-n, 10); // -3
// …although it doesn’t replace Math.floor() for negative numbers
Math.floor(-n); // -4

Pojedyncza negacja bitowa (~) oblicza -(parseInt(n, 10) + 1), więc dwie negacje bitowe zwrócą -(-(parseInt(n, 10) + 1) + 1).

Należy zauważyć, że z tych trzech alternatyw, n|n wydaje się być najszybszy.

Aktualizacja: Dokładniejsze benchmarki tutaj: http://jsperf.com/rounding-numbers-down

(Jak napisano na )

 24
Author: Mathias Bynens,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-05-23 11:47:05

A prawdziwe życie przykład :

^ bitowy XOR jako I/O toggler

Używane jak value ^= 1 zmieni się przy każdym wywołaniu value na 0, 1, 0, 1 ...

function toggle(evt) {
  evt.target.IO ^= 1;                                    // Bitwise XOR as 1/0 toggler
  evt.target.textContent = evt.target.IO ? "ON" : "OFF"; // Unleash your ideas
}

[...document.querySelectorAll("button")].forEach( el =>
  el.addEventListener("click", toggle)
);
<button>OFF</button>
<button>OFF</button>
<button>OFF</button>
 16
Author: Roko C. Buljan,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-04-26 17:31:51

Biorąc pod uwagę postęp Javascript (szczególnie w przypadku nodejs, który umożliwia programowanie po stronie serwera z js), w JS jest coraz bardziej złożony kod. Oto kilka przykładów, w których użyłem operatorów bitowych:

  • Operacje na adresie IP:

    //computes the broadcast address based on the mask and a host address
    broadcast = (ip & mask) | (mask ^ 0xFFFFFFFF)
    
    
    //converts a number to an ip adress 
    sprintf(ip, "%i.%i.%i.%i", ((ip_int >> 24) & 0x000000FF),
                             ((ip_int >> 16) & 0x000000FF),
                             ((ip_int >>  8) & 0x000000FF),
                             ( ip_int        & 0x000000FF));
    

Uwaga: Jest to kod C, ale JS jest prawie identyczny

  • algorytmy CRC dużo z nich korzystają

Zobacz wpis w Wikipedii na ten

  • Screen operacje rozdzielczości
 14
Author: Bogdan Gavril MSFT,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-04-09 10:59:18

Aby stwierdzić, czy liczba jest nieparzysta:

function isOdd(number) {
    return !!(number & 1);
}

isOdd(1); // true, 1 is odd
isOdd(2); // false, 2 is not odd
isOdd(357); // true, 357 is odd

Szybciej niż Moduł-użyj tam, gdzie liczy się wydajność naprawdę !

 12
Author: danwellman,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-09-24 19:00:23

Kilka innych przykładów użycia bitwise not I double bitwise not:

Działanie podłogi

~~2.5    // 2
~~2.1    // 2
~~(-2.5) // -2

Sprawdź czy indexOf zwrócił -1 czy nie

var foo = 'abc';
!~foo.indexOf('bar'); // true
 11
Author: Pavel Podlipensky,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-10-06 10:43:31

Możesz ich użyć do przerzucania wartości logicznej:

var foo = 1;
var bar = 0;
alert(foo ^= 1);
alert(bar ^= 1);

Jest to jednak trochę głupie i w większości operatorów bitowych nie ma wielu aplikacji w Javascript.

 9
Author: Andrew Hare,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-03-17 12:49:13

Bitmaski.

Szeroko stosowany, na przykład w zdarzeniach JS.

 6
Author: Yuval Adam,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-03-17 12:50:05
var arr = ['abc', 'xyz']

Zirytowany do napisania

if (arr.indexOf('abc') > -1) {
  // 'abc' is in arr
}

if (arr.indexOf('def') === -1) {
  // 'def' is not in arr
}

Aby sprawdzić, czy coś jest wewnątrz tablicy?

Możesz użyć operatora bitowego ~ w następujący sposób:

if (~arr.indexOf('abc')) {
  // 'abc' is in arr
}

if (! ~arr.indexOf('def')) {
  // 'def' is not in arr
}
 6
Author: Yann Bertrand,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-06-19 09:40:18

Użyłem go raz dla uprawnienia widget. Uprawnienia do plików w Uniksie są maską bitową, więc aby ją przeanalizować, musisz użyć operacji bitowych.

 2
Author: troelskn,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-03-17 12:52:41

Używam ich do spłaszczenia trzech liczb do 1 jako sposobu przechowywania wielowymiarowych tablic w Uint16Array . Oto fragment gry voxel, którą rozwijam:

function Chunk() {
  this._blocks = new Uint16Array(32768);
  this._networkUpdates = [];
}

Chunk.prototype.getBlock = function(x, y, z) {
  return this._blocks[y + (x << 5) + (z << 10)];
};

Chunk.prototype.setBlock = function(x, y, z, value) {
  this._blocks[y + (x << 5) + (z << 10)] = value;
  this._networkUpdates.push(value + (y << 15) + (x << 20) + (z << 25));
};

Chunk.prototype.getUpdates = function() {
  return this._networkUpdates;
};

Chunk.prototype.processUpdate = function(update) {
  // this._blocks[Math.floor(update / 65536)] = update % 65536;
  this._blocks[update >> 16] = update & 65535;
};

var chunk = new Chunk();
chunk.setBlock(10, 5, 4);
alert(chunk.getBlock(10, 5, 4));
alert(chunk.getUpdates()[0]);
 1
Author: Bardi Harborow,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-03-29 08:43:00

Wydają się być bardzo przydatne, gdy pracujesz z wartościami szesnastkowymi i bitami. Ponieważ 4 bity mogą reprezentować 0 do F.

1111 = F 1111 1111 = FF.

 0
Author: eternauta,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-11-12 05:41:01

Przykład użycia Node.js

Zakładając, że masz plik (zwany mnożeniem.js) z tymi treściami można uruchomić

`node multiply <number> <number>`

I uzyskać wynik zgodny z użyciem operatora mnożenia na tych samych dwóch liczbach. Przesunięcie bitów zachodzące w funkcji Mulitply jest przykładem tego, jak wziąć maskę bitową reprezentującą jedną liczbę i użyć jej do odwrócenia bitów w innej liczbie do szybkich operacji.

var a, b, input = process.argv.slice(2);

var printUsage = function() {
  console.log('USAGE:');
  console.log('  node multiply <number> <number>');
}

if(input[0] === '--help') {+
  printUsage();
  process.exit(0);
}

if(input.length !== 2) {
  printUsage();
  process.exit(9);
}

if(isNaN(+input[0]) || isNaN(+input[1])) {
  printUsage();
  process.exit(9);
}

// Okay, safe to proceed

a = parseInt(input[0]),
b = parseInt(input[1]);

var Multiply = function(a,b) {
  var x = a, y = b, z = 0;

  while( x > 0 ) {
    if(x % 2 === 1) {
      z = z + y;
    }
    y = y << 1;
    x = x >> 1;
  }

  return z;
}

var result = Multiply(a,b);

console.log(result);
 0
Author: mysterlune,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-04-09 23:00:59

Ta odpowiedź zawiera wyjaśnienia Odpowiedzi Marka .

Czytając te wyjaśnienia i uruchamiając fragment kodu można uzyskać pomysł.

var hex = 'ffaadd';
var rgb = parseInt(hex, 16); // rgb value is 16755421 in decimal = 111111111010101011011101 in binary = total 24 bits


var red   = (rgb >> 16) & 0xFF; // returns 255
var green = (rgb >> 8) & 0xFF;  // returns 170
var blue  = rgb & 0xFF;         // returns 221  

// HOW IS IT

// There are two bitwise operation as named SHIFTING and AND operations.
// SHIFTING is an operation the bits are shifted toward given direction by adding 0 (zero) bit for vacated bit fields.
// AND is an operation which is the same with multiplying in Math. For instance, if 9th bit of the given first bit-set is 0
// and 9th bit of the given second bit-set is 1, the new value will be 0 because of 0 x 1 = 0 in math.

// 0xFF (000000000000000011111111 in binary) - used for to evaluate only last 8 bits of a given another bit-set by performing bitwise AND (&) operation. 
// The count of bits is 24 and the first 16 bits of 0xFF value consist of zero (0) value. Rest of bit-set consists of one (1) value.
console.log("0xFF \t\t\t\t: ", 0xFF) 


// 111111111010101011011101 -> bits of rgb variable
// 000000000000000011111111 -> 255 after (rgb >> 16) shifting operation
// 000000000000000011111111 -> 255 complement (changes the first 16 bits and does nothing for the last 8 bits)
// 000000000000000011111111 -> result bits after performing bitwise & operation
console.log("Red - (rgb >> 16) & 0xFF \t: ", (rgb >> 16) & 0xFF) // used for to evaluate the first 8 bits

// 111111111010101011011101 -> bits of rgb variable
// 000000001111111110101010 -> 65450 -> 'ffaa'
// 000000000000000011111111 -> 255 complement (changes the first 16 bits and does nothing for the last 8 bits)
// 000000000000000010101010 -> result bits after performing bitwise & operation
// calculation -> 000000001111111110101010 & 000000000000000011111111 = 000000000000000010101010 = 170 in decimal = 'aa' in hex-decimal
console.log("Green - (rgb >> 8) & 0xFF \t: ", (rgb >> 8) & 0xFF) // used for to evaluate the middle 8 bits 

// 111111111010101011011101 -> 'ffaadd'
// 000000000000000011111111 -> 255 complement (changes the first 16 bits and does nothing for the last 8 bits)
// 000000000000000011011101 -> result bits after performing bitwise & operation 
// calculation -> 111111111010101011011101 & 000000000000000011111111 = 221 in decimal = 'dd' in hex-decimal
console.log("Blue - rgb & 0xFF \t\t: ", rgb & 0xFF) // // used for to evaluate the last 8 bits.

console.log("It means that `FFAADD` hex-decimal value specifies the same color with rgb(255, 170, 221)")

/* console.log(red)
console.log(green)
console.log(blue) */
 0
Author: efkan,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-03-19 10:21:11

Właśnie znalazłem to pytanie, próbując potwierdzić, czy bitowy operator AND również był & w Javascript.

Skoro prosiłeś o Przykład:

if ($('input[id="user[privileges]"]').length > 0) {
    $('#privileges button').each(function () {
        if (parseInt($('input[id="user[privileges]"]').val()) & parseInt($(this).attr('value'))) {
            $(this).button('toggle');
        }
    });
}

Zapełnia stan przycisków z jQuery podaną wartością maski bitowej ukrytego pola:

  • none = 0
  • user = 1
  • administrator = 2
  • user + administrator = 3
 -1
Author: Alix Axel,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-07-16 04:04:26