Working with Flags
Bitwise operators are great for flags and permissions. Each bit can represent a feature on/off.
Use `|` to add flags, `&` to test them, and `^` to toggle.
JavaScript Tutorial
Bitwise operators work directly with the binary representation of numbers. They are powerful for flags, masks, and low-level optimizations.
Because they coerce numbers to 32-bit integers, you should use them carefully and intentionally.
Bitwise logic can reduce memory usage and make permission checks fast, but it can also hide intent.
Knowing when and how to use bitwise operators helps you balance performance and readability.
a & b // AND
a | b // OR
a ^ b // XOR
~a // NOT
a << b // left shift
a >> b // right shift (sign-preserving)
a >>> b // unsigned right shiftconst READ = 1; // 0001
const WRITE = 2; // 0010
const EXEC = 4; // 0100
let perms = READ | WRITE; // 0011
const canWrite = (perms & WRITE) !== 0;
console.log(perms, canWrite);Use bitwise OR to set flags and AND to check them.
const DARK = 1; // 0001
let flags = 0;
flags ^= DARK; // toggle on
flags ^= DARK; // toggle off
console.log(flags);XOR flips bits: on becomes off, off becomes on.
Bitwise operators are great for flags and permissions. Each bit can represent a feature on/off.
Use `|` to add flags, `&` to test them, and `^` to toggle.
Left shift (`<<`) multiplies by powers of two. Right shift (`>>`) divides by powers of two while keeping the sign.
Unsigned right shift (`>>>`) fills with zero on the left and treats numbers as unsigned 32-bit integers.
Bitwise operators convert values to 32-bit integers. This can be fast but may lose precision with large numbers.
Avoid bitwise ops on floating-point values unless you know the conversion is safe.
Feature toggles, permissions, caching strategies, and graphics work commonly use bitwise logic.
They are powerful but less readable, so use them when the benefit is clear.
console.log(5 << 1); // 10 (1010)
console.log(8 >> 1); // 4
console.log(-8 >>> 1); // large unsigned numberShifts multiply/divide by powers of two, or zero-fill with >>>.
console.log(~5); // -6
// Useful for quick index checks
const idx = "hello".indexOf("e");
console.log(~idx); // non-zero means foundBitwise NOT flips all bits. It can be used in clever patterns, though readability matters.
Without
// Without flags
const canRead = true;
const canWrite = true;
const canExec = false;With
// With flags
const READ = 1;
const WRITE = 2;
const EXEC = 4;
let perms = READ | WRITE;
const canExec = (perms & EXEC) !== 0;Bitwise ops coerce to 32-bit ints. Avoid on large numbers.
Prefer clear boolean logic unless you need flags or masks.
Bitwise ops drop fractional parts.
Unsigned shift always fills with zeros and treats numbers as unsigned.
They are converted to 32-bit signed integers.
Use AND: (flags & FLAG) !== 0.
>> preserves sign; >>> shifts in zeros and treats as unsigned.
Practice: Create READ, WRITE, and DELETE flags and check if a user has DELETE permission.
const READ = 1;
const WRITE = 2;
const DELETE = 4;
let perms = READ | WRITE;
// TODO: check if DELETE is enabled
One Possible Solution
const READ = 1;
const WRITE = 2;
const DELETE = 4;
let perms = READ | WRITE;
const canDelete = (perms & DELETE) !== 0;
console.log(canDelete);Bitwise NOT flips all bits. In two's complement, that results in -(n+1).
They are optimized but only helpful when you actually need bit-level manipulation.
>> keeps the sign bit; >>> shifts in zeros and treats the number as unsigned.
When you need compact, fast permission or feature toggles.
Run the flag examples and toggle bits to see how permissions change.