Skip to content
← All Tools
๐Ÿ”’All processing in your browser ๐ŸšซNo uploads stored ๐Ÿ›ก๏ธPrivacy-first conversion tools โœ“No login required
Tutorial

Bitwise Operations in JavaScript: A Practical Guide

Bill Crawford — Developer Guide — 2026  ยท  Last updated September 12, 2025

Bitwise operators work directly on the binary representation of numbers. JavaScript converts numbers to 32-bit signed integers for bitwise operations, applies the operation bit-by-bit, then converts the result back to a JavaScript number. They're faster than their mathematical equivalents for certain tasks and essential for working with packed data, hardware interfaces, and graphics.

Connect on LinkedIn โ†’

Visualise binary conversions: Our Number Base Converter shows decimal, hex, binary, and octal side-by-side so you can see exactly what the bits look like.

Open Number Base Converter โ†’

Table of Contents

  1. The Six Bitwise Operators
  2. AND: Masking and Testing Flags
  3. OR: Setting Flags
  4. XOR: Toggling and Swapping
  5. NOT: Inverting Bits
  6. Shift Operators
  7. Real-World: RGB Color Manipulation
  8. Gotchas in JavaScript

The Six Bitwise Operators

OperatorSymbolEffect
AND&1 only if both bits are 1
OR|1 if either bit is 1
XOR^1 if bits are different
NOT~Flips all bits
Left shift<<Shifts bits left, fills with 0
Right shift>>Shifts bits right, preserves sign

AND: Masking and Testing Flags

// Test if a bit is set
const value = 0b1010;  // 10 in decimal
value & 0b0010;  // 0b0010 = 2 โ€” the bit IS set
value & 0b0100;  // 0b0000 = 0 โ€” the bit is NOT set

// Practical: check if a number is even or odd
// Even numbers have 0 in the lowest bit; odd numbers have 1
const isOdd  = n => (n & 1) === 1;
const isEven = n => (n & 1) === 0;

// Extract the lower byte of a 32-bit integer
const lower8bits = value & 0xFF;

OR: Setting Flags

// Permission flags
const READ    = 1;   // 0b001
const WRITE   = 2;   // 0b010
const EXECUTE = 4;   // 0b100

// Grant read and write permission
let perms = READ | WRITE;  // 0b011 = 3

// Grant execute permission to existing perms
perms = perms | EXECUTE;   // 0b111 = 7 (rwx)

XOR: Toggling and Swapping

// Toggle a bit
let flags = 0b1010;
flags ^= 0b0010;  // toggle bit 1 โ†’ 0b1000
flags ^= 0b0010;  // toggle again โ†’ 0b1010 (back to original)

// XOR swap (no temp variable needed)
let a = 5, b = 3;
a ^= b;  // a = 6 (5 XOR 3)
b ^= a;  // b = 5 (3 XOR 6)
a ^= b;  // a = 3 (6 XOR 5)
// a=3, b=5 โ€” swapped!

// Simple (not cryptographic) hash/checksum
function xorChecksum(bytes) {
  return bytes.reduce((acc, byte) => acc ^ byte, 0);
}

NOT: Inverting Bits

// ~ inverts all 32 bits and the result for positive n is -(n+1)
~5    // -6
~0    // -1
~-1   // 0

// Practical: ~~ as a fast Math.floor for positive numbers
~~3.7  // 3
~~-3.7 // -3 (careful โ€” differs from Math.floor for negatives)

// Remove a permission flag
let perms = 0b111;  // rwx
const WRITE = 0b010;
perms &= ~WRITE;    // perms = 0b101 โ€” write bit cleared

Shift Operators

// Left shift: multiply by 2 per shift
1 << 0   // 1
1 << 1   // 2
1 << 2   // 4
1 << 8   // 256
1 << 10  // 1024

// Right shift: divide by 2 per shift (integer division)
256 >> 1  // 128
256 >> 4  // 16

// Practical: create a bit mask for position n
const maskForBit = n => 1 << n;
maskForBit(3)  // 0b1000 = 8

// Extract a byte from a 32-bit integer
const getbyte = (n, pos) => (n >> (pos * 8)) & 0xFF;
getbyte(0xFF5733, 1)  // 0x57 = 87 (green channel)

Real-World: RGB Color Manipulation

// Pack RGB into single integer
function rgbToInt(r, g, b) {
  return (r << 16) | (g << 8) | b;
}

// Unpack RGB from single integer
function intToRgb(color) {
  return {
    r: (color >> 16) & 0xFF,
    g: (color >> 8)  & 0xFF,
    b:  color        & 0xFF
  };
}

// Darken a color by 50%
function darken(color) {
  const { r, g, b } = intToRgb(color);
  return rgbToInt(r >> 1, g >> 1, b >> 1);
}

// Blend two colors at 50/50
function blend(c1, c2) {
  const a = intToRgb(c1), b = intToRgb(c2);
  return rgbToInt(
    (a.r + b.r) >> 1,
    (a.g + b.g) >> 1,
    (a.b + b.b) >> 1
  );
}

Gotchas in JavaScript

JavaScript converts to 32-bit signed integer before bitwise operations. Numbers larger than 2,147,483,647 will produce unexpected results. For large integers use BigInt: BigInt(value) & BigInt(mask).

The unsigned right shift operator >>> is unique to JavaScript โ€” it fills with zeros regardless of sign, treating the number as unsigned. Use it when you want the result to always be a non-negative integer: -1 >>> 0 gives 4294967295.

Operator precedence. Bitwise operators have lower precedence than comparison operators. Always use parentheses: (n & MASK) !== 0, not n & MASK !== 0 (which evaluates as n & (MASK !== 0)).

Further reading: MDN โ€” Bitwise Operators

BC
Bill Crawford
Founder, Data Conversion Center

Bill Crawford is a data systems developer and technical founder with over 30 years of professional experience in accounting, finance, and business operations.

He holds a Bachelor's degree in Accounting and has spent more than three decades working within financial and operational environments. Over the past 10 years, he has been heavily involved in the development, implementation, and refinement of financial and enterprise data systems for both Fortune 500 companies and smaller organizations.

His work bridges finance and technology — combining deep domain knowledge in structured reporting and accounting workflows with hands-on SQL development and database architecture experience.

Bill founded DataConversionCenter.com to build practical, browser-based tools that simplify complex data challenges, including:

Rather than focusing on theoretical examples, his tools and articles are informed by real-world challenges encountered in enterprise reporting systems, financial databases, and operational data environments.

Professional Background

Bill's mission is to reduce friction in data workflows — particularly for professionals working with structured financial, operational, and reporting data.