78

I've read 'what are bitwise operators?', so I know what bitwise operators are but I'm still not clear on how one might use them. Can anyone offer any real-world examples of where a bitwise operator would be useful in JavaScript?

Thanks.

Edit:

Just digging into the jQuery source I've found a couple of places where bitwise operators are used, for example: (only the & 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;
mikemaccana
  • 110,530
  • 99
  • 389
  • 494
James
  • 109,676
  • 31
  • 162
  • 175

16 Answers16

75

Example:

Parses hexadecimal value to get RGB color values.

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  
timetowonder
  • 5,121
  • 5
  • 34
  • 48
Mark
  • 16,772
  • 9
  • 42
  • 55
48

I heavily use bitwise operators for numerical convertions in production scripts, because sometimes they're much faster than their Math or parseInt equivalents.

The price I have to pay is code readability. So I usualy use Math in development and bitwise in production.

You can find some performance tricks on jsperf.com.

As you can see, browsers don't optimize Math.ceil and parseInt for years, so I predict bitwise will be faster and shorter way to do things in furure as well.

Some further reading on SO...


Bonus: cheat sheet for | 0 : an easy and fast way to convert anything to integer:

( 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;

and some magic for me:

3 | '0px' === 3;
Community
  • 1
  • 1
Dan
  • 55,715
  • 40
  • 116
  • 154
  • or use closure compiler in advanced mode which does all these optimisations for you – Pawel May 14 '16 at 15:59
  • 2
    this is not a good answer. At first it looks like a reference and having much information (I even upvoted it yesterday), but after a more thorough look into it this turns out not to be true. – d.k Jul 16 '16 at 08:42
  • 4
    All this 20 lines or so of examples could have been expressed in a single sentence: **The bitwise operators work with 32-bit, two's complement big-endian (32-bit, for short) representations of numbers, so any of their operands is converted to this format according to the following rules: a number is converted from the IEEE-754 64-bit format to 32-bit and anything else is first converted to a number as specified in the ECMAScript spec (namely, for objects (that is objects, arrays, functions) via a call to its valueOf method) and then this number is converted to the 32-bit format** – d.k Jul 16 '16 at 08:48
  • 1
    You can try this: `'use strict'; Function.prototype.valueOf = function() {return 2;};console.log(( (function(){})|0 ) === 0);`, and you'll see that your last two examples are not correct and so on. – d.k Jul 16 '16 at 08:53
  • @Pacerier, no, I don't – d.k Feb 20 '17 at 19:04
  • 4
    @user907860: Actually, ideally both the single sentence *and* the lines of code should be present. The sentence will explain it concisely for more advanced programmers such as yourself, but for people like me who've never worked with another language and only know Javascript, all your talk of 32-bit and two's complement and big-endian are difficult to understand. I'm a hands-on learner, and the code completely helped me (though granted, it didn't need quite *that* much repetition). – Marcus Hughes Jan 15 '18 at 06:44
25

In JavaScript, you can use a double bitwise negation (~~n) as a replacement for Math.floor(n) (if n is a positive number) or parseInt(n, 10) (even if n is negative). n|n and n&n always yield the same results as ~~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

A single bitwise negation (~) calculates -(parseInt(n, 10) + 1), so two bitwise negations will return -(-(parseInt(n, 10) + 1) + 1).

It should be noted that of these three alternatives, n|n appears to be the fastest.

Update: More accurate benchmarks here: http://jsperf.com/rounding-numbers-down

(As posted on Strangest language feature)

Community
  • 1
  • 1
Mathias Bynens
  • 144,855
  • 52
  • 216
  • 248
  • 1
    `n << 0;` is now fastest on V8. `n | 0;` is very close behind and is what I use. – Bardi Harborow Mar 29 '15 at 08:32
  • @BardiHarborow, What about `n >>> 0`? – Pacerier Feb 17 '17 at 04:46
  • Rather than how can you use it, a more pertinent question might be, "Why would you use it?" Are any potential performance gains from this worth the code readability? – Ryan May 08 '17 at 08:56
  • Can you explain why the decimal is just truncated every time you use a bitwise operator? Do bitwise operators only work on integers? – Captainlonate May 27 '18 at 16:28
  • @Ryan code readability is easily corrected with two slashes followed by words, such as `wetMop = n|0; // bitwise version of Math.floor` – Myndex Oct 28 '20 at 21:52
  • "…although it doesn’t replace Math.floor() for negative numbers" so would that mean it's more like `Math.trunc(number)` – Samathingamajig Nov 14 '20 at 05:17
24

^ bitwise XOR as toggler

value ^= 1 will change on every call the value to 0, 1, 0, 1, ... , (it's basically similar to: boolVal != boolVal):

function toggle(evt) {
  const EL = evt.currentTarget;
  EL.isOn ^= 1; // Bitwise toggle
  EL.textContent = EL.isOn ? "ON" : "OFF"; // Unleash your ideas
}

document.querySelectorAll("button").forEach( el =>
  el.addEventListener("click", toggle)
);
<button>OFF</button>
<button>OFF</button>
<button>OFF</button>
Roko C. Buljan
  • 196,159
  • 39
  • 305
  • 313
16

To tell if a number is odd:

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

Faster than modulus - use where performance really counts!

danwellman
  • 9,068
  • 8
  • 60
  • 88
  • 4
    Why not: function isOdd(number) { return x % 2; } – Duc Filan Jun 21 '17 at 00:20
  • 2
    Performance. https://jsperf.com/modulo-vs-bitwise/8 Bitwise is faster across most browsers (or, it was at the time the answer was posted, in recent Chrome's there is not much difference tbf – danwellman Jan 15 '18 at 09:05
16

Given the advances Javascript is making (especially with nodejs that allows server side programming with js), there is more and more complex code in JS. Here are a couple of instances where I have used bitwise operators:

  • IP address operations:

    //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));
    

Note: this is C code, but JS is almost identical

  • CRC algorithms uses them a lot

Check out the wikipedia entry on this

  • Screen resolution operations
Bogdan Gavril MSFT
  • 20,615
  • 10
  • 53
  • 74
13

Few other examples of how to use bitwise not and double bitwise not:

Floor operation

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

Check whether indexOf returned -1 or not

var foo = 'abc';
!~foo.indexOf('bar'); // true
John Weisz
  • 30,137
  • 13
  • 89
  • 132
Pavel Podlipensky
  • 8,201
  • 5
  • 42
  • 53
11

You can use them for flipping a boolean value:

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

This is a bit silly though and for the most part bitwise operators do not have many applications in Javascript.

Andrew Hare
  • 344,730
  • 71
  • 640
  • 635
8
var arr = ['abc', 'xyz']

Annoyed to write

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

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

to check if something is inside an array?

You can use the bitwise operator ~ like so:

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

if (! ~arr.indexOf('def')) {
  // 'def' is not in arr
}
Yann Bertrand
  • 3,084
  • 1
  • 22
  • 38
4

Bitmasks.

Used extensively, for example, in JS events.

Yuval Adam
  • 161,610
  • 92
  • 305
  • 395
3

This answer contains explanations of Mark's answer.

By reading these explanations and running the code snippet an idea can be gained.

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) */
efkan
  • 12,991
  • 6
  • 73
  • 106
3

I've used it once for a permissions widget. File permissions in unix are a bitmask, so to parse it, you need to use bit operations.

troelskn
  • 115,121
  • 27
  • 131
  • 155
2

I'm using them to flatten three numbers into 1 as a way of storing multidimensional arrays in a Uint16Array. Here is a snippet of a voxel game I'm developing:

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]);
Bardi Harborow
  • 1,803
  • 1
  • 28
  • 41
0

They seem to be very useful when you work with hex values and bits. Since 4 bits can represent 0 to F.

1111 = F 1111 1111 = FF.

eternauta
  • 53
  • 5
0

Example using Node.js

Presuming you had a file (called multiply.js) with these contents, you could run

`node multiply <number> <number>`

and get an output consistent with using the multiplication operator on the same two numbers. The bit shifting going on in the Mulitply function is an example of how to take the bit mask representing one number and use it to flip bits in another number for fast operations.

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);
mysterlune
  • 1,691
  • 1
  • 12
  • 12
-1

I just found this question trying to confirm if the bitwise AND operator also was & in Javascript.

Since you asked for an example:

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');
        }
    });
}

It populates the state of buttons with jQuery given a bitmask value of a hidden field:

  • none = 0
  • user = 1
  • administrator = 2
  • user + administrator = 3
Alix Axel
  • 151,645
  • 95
  • 393
  • 500