JavaScript Bitwise Operations

Working with binary representations and bit manipulation

🔢 What are Bitwise Operations?

Bitwise operations work directly with the binary representation of numbers. They manipulate individual bits and are very fast, making them useful for performance-critical applications and low-level programming.


// Simple bitwise AND example
console.log(5 & 3); // 1
// 5 in binary: 101
// 3 in binary: 011
// Result:      001 (which is 1)
                                    

Output:

1

Bitwise Operators

🔗

AND (&)

Returns 1 if both bits are 1

console.log(5 & 3); // 1
// 101 & 011 = 001
âž•

OR (|)

Returns 1 if either bit is 1

console.log(5 | 3); // 7
// 101 | 011 = 111
âš¡

XOR (^)

Returns 1 if bits are different

console.log(5 ^ 3); // 6
// 101 ^ 011 = 110
🔄

NOT (~)

Flips all bits (inverts)

console.log(~5); // -6
// ~101 = ...11111010

🔹 Basic Bitwise Operations

Understanding the fundamental bitwise operators:

let a = 5;  // Binary: 101
let b = 3;  // Binary: 011

// AND (&) - both bits must be 1
console.log("5 & 3 =", a & b); // 1 (binary: 001)

// OR (|) - at least one bit must be 1
console.log("5 | 3 =", a | b); // 7 (binary: 111)

// XOR (^) - bits must be different
console.log("5 ^ 3 =", a ^ b); // 6 (binary: 110)

// NOT (~) - flips all bits
console.log("~5 =", ~a); // -6 (two's complement)
console.log("~3 =", ~b); // -4

// Helper function to see binary representation
function toBinary(num) {
    return (num >>> 0).toString(2).padStart(8, '0');
}

console.log("5 in binary:", toBinary(5));
console.log("3 in binary:", toBinary(3));
console.log("5 & 3 in binary:", toBinary(5 & 3));
console.log("5 | 3 in binary:", toBinary(5 | 3));
console.log("5 ^ 3 in binary:", toBinary(5 ^ 3));

Output:

5 & 3 = 1
5 | 3 = 7
5 ^ 3 = 6
~5 = -6
~3 = -4
5 in binary: 00000101
3 in binary: 00000011
5 & 3 in binary: 00000001
5 | 3 in binary: 00000111
5 ^ 3 in binary: 00000110

🔹 Bit Shift Operations

Moving bits left or right:

let num = 5; // Binary: 101

// Left shift (<<) - multiply by 2^n
console.log("5 << 1 =", num << 1); // 10 (multiply by 2)
console.log("5 << 2 =", num << 2); // 20 (multiply by 4)
console.log("5 << 3 =", num << 3); // 40 (multiply by 8)

// Right shift (>>) - divide by 2^n (signed)
console.log("20 >> 1 =", 20 >> 1); // 10 (divide by 2)
console.log("20 >> 2 =", 20 >> 2); // 5 (divide by 4)

// Unsigned right shift (>>>) - always positive
console.log("-5 >> 1 =", -5 >> 1); // -3 (signed)
console.log("-5 >>> 1 =", -5 >>> 1); // 2147483645 (unsigned)

// Visual representation
function showShift(num, shift, direction) {
    let original = toBinary(num);
    let result = direction === 'left' ? num << shift : num >> shift;
    let resultBinary = toBinary(result);
    
    console.log(`${num} ${direction === 'left' ? '<<' : '>>'} ${shift}:`);
    console.log(`  Original: ${original} (${num})`);
    console.log(`  Result:   ${resultBinary} (${result})`);
}

showShift(5, 2, 'left');
showShift(20, 2, 'right');

Output:

5 << 1 = 10
5 << 2 = 20
5 << 3 = 40
20 >> 1 = 10
20 >> 2 = 5
-5 >> 1 = -3
-5 >>> 1 = 2147483645
5 << 2:
Original: 00000101 (5)
Result: 00010100 (20)
20 >> 2:
Original: 00010100 (20)
Result: 00000101 (5)

🔹 Practical Bitwise Applications

Real-world uses of bitwise operations:

// 1. Check if number is even or odd
function isEven(num) {
    return (num & 1) === 0; // Last bit is 0 for even numbers
}

console.log("Is 4 even?", isEven(4)); // true
console.log("Is 5 even?", isEven(5)); // false

// 2. Fast multiplication/division by powers of 2
function fastMultiply(num, power) {
    return num << power; // Multiply by 2^power
}

function fastDivide(num, power) {
    return num >> power; // Divide by 2^power
}

console.log("8 * 4 (fast):", fastMultiply(8, 2)); // 32
console.log("32 / 8 (fast):", fastDivide(32, 3)); // 4

// 3. Swap two numbers without temporary variable
function bitwiseSwap(a, b) {
    console.log(`Before swap: a=${a}, b=${b}`);
    a = a ^ b;
    b = a ^ b;
    a = a ^ b;
    console.log(`After swap: a=${a}, b=${b}`);
    return [a, b];
}

bitwiseSwap(5, 10);

// 4. Set, clear, and toggle specific bits
function setBit(num, position) {
    return num | (1 << position);
}

function clearBit(num, position) {
    return num & ~(1 << position);
}

function toggleBit(num, position) {
    return num ^ (1 << position);
}

function checkBit(num, position) {
    return (num & (1 << position)) !== 0;
}

let flags = 0; // Start with all flags off
console.log("Initial flags:", toBinary(flags));

flags = setBit(flags, 2); // Set bit 2
console.log("Set bit 2:", toBinary(flags));

flags = setBit(flags, 5); // Set bit 5
console.log("Set bit 5:", toBinary(flags));

console.log("Is bit 2 set?", checkBit(flags, 2)); // true
console.log("Is bit 3 set?", checkBit(flags, 3)); // false

flags = toggleBit(flags, 2); // Toggle bit 2
console.log("Toggle bit 2:", toBinary(flags));

Output:

Is 4 even? true
Is 5 even? false
8 * 4 (fast): 32
32 / 8 (fast): 4
Before swap: a=5, b=10
After swap: a=10, b=5
Initial flags: 00000000
Set bit 2: 00000100
Set bit 5: 00100100
Is bit 2 set? true
Is bit 3 set? false
Toggle bit 2: 00100000

🔹 Color Manipulation with Bitwise

Working with RGB colors using bitwise operations:

// RGB color as a single number (0xRRGGBB)
let color = 0xFF5733; // Orange color

// Extract RGB components
function getRed(color) {
    return (color >> 16) & 0xFF;
}

function getGreen(color) {
    return (color >> 8) & 0xFF;
}

function getBlue(color) {
    return color & 0xFF;
}

console.log("Color:", color.toString(16).toUpperCase());
console.log("Red component:", getRed(color));
console.log("Green component:", getGreen(color));
console.log("Blue component:", getBlue(color));

// Create color from RGB components
function createColor(r, g, b) {
    return (r << 16) | (g << 8) | b;
}

let newColor = createColor(128, 255, 64);
console.log("New color:", newColor.toString(16).toUpperCase());

// Modify color components
function setRed(color, red) {
    return (color & 0x00FFFF) | (red << 16);
}

function setGreen(color, green) {
    return (color & 0xFF00FF) | (green << 8);
}

function setBlue(color, blue) {
    return (color & 0xFFFF00) | blue;
}

let modifiedColor = setGreen(color, 128);
console.log("Modified color:", modifiedColor.toString(16).toUpperCase());

Output:

Color: FF5733
Red component: 255
Green component: 87
Blue component: 51
New color: 80FF40
Modified color: FF8033

🔹 Permission Systems with Bitwise

Using bitwise operations for permission flags:

// Permission constants (powers of 2)
const PERMISSIONS = {
    READ: 1,      // 001
    WRITE: 2,     // 010
    EXECUTE: 4,   // 100
    DELETE: 8,    // 1000
    ADMIN: 16     // 10000
};

// User permissions
let userPermissions = 0;

// Grant permissions
function grantPermission(permissions, permission) {
    return permissions | permission;
}

// Revoke permissions
function revokePermission(permissions, permission) {
    return permissions & ~permission;
}

// Check if user has permission
function hasPermission(permissions, permission) {
    return (permissions & permission) === permission;
}

// Grant some permissions
userPermissions = grantPermission(userPermissions, PERMISSIONS.READ);
userPermissions = grantPermission(userPermissions, PERMISSIONS.WRITE);

console.log("User permissions:", userPermissions.toString(2).padStart(5, '0'));
console.log("Can read?", hasPermission(userPermissions, PERMISSIONS.READ));
console.log("Can write?", hasPermission(userPermissions, PERMISSIONS.WRITE));
console.log("Can execute?", hasPermission(userPermissions, PERMISSIONS.EXECUTE));

// Grant multiple permissions at once
userPermissions = grantPermission(userPermissions, PERMISSIONS.EXECUTE | PERMISSIONS.DELETE);
console.log("Updated permissions:", userPermissions.toString(2).padStart(5, '0'));

// Check multiple permissions
function hasAllPermissions(permissions, requiredPermissions) {
    return (permissions & requiredPermissions) === requiredPermissions;
}

let requiredForAdmin = PERMISSIONS.READ | PERMISSIONS.WRITE | PERMISSIONS.EXECUTE;
console.log("Has admin requirements?", hasAllPermissions(userPermissions, requiredForAdmin));

Output:

User permissions: 00011
Can read? true
Can write? true
Can execute? false
Updated permissions: 01111
Has admin requirements? true

🧠 Test Your Knowledge

What does 5 & 3 equal?