JavaScript Operators

Learn every JavaScript operator - from arithmetic and comparison to the powerful nullish coalescing and optional chaining operators introduced in ES2020.

Beginner 10 min read 11 examples

Arithmetic Operators

Standard math operations plus a few JavaScript-specific ones:

JavaScript
console.log(10 + 3);   // 13 - addition
console.log(10 - 3);   // 7  - subtraction
console.log(10 * 3);   // 30 - multiplication
console.log(10 / 3);   // 3.3333... - division (always float)
console.log(10 % 3);   // 1  - modulus (remainder)
console.log(2 ** 10);  // 1024 - exponentiation (ES2016)

// Increment and decrement
let x = 5;
console.log(x++);  // 5  - post-increment: returns THEN increments
console.log(x);    // 6
console.log(++x);  // 7  - pre-increment: increments THEN returns
console.log(x--);  // 7  - post-decrement
console.log(x);    // 6

// Unary plus and minus
console.log(+"42");  // 42  - convert string to number
console.log(-"42");  // -42
console.log(+true);  // 1
console.log(+false); // 0
console.log(+null);  // 0
console.log(+undefined); // NaN

// + with strings (concatenation - not addition)
console.log("5" + 3);  // "53" (string concat)
console.log(5 + "3");  // "53"
console.log(5 - "3");  // 2   (- always coerces to number)

Assignment Operators

Shorthand operators that combine assignment with another operation:

JavaScript
let n = 10;

n += 5;   // n = n + 5  -> 15
n -= 3;   // n = n - 3  -> 12
n *= 2;   // n = n * 2  -> 24
n /= 4;   // n = n / 4  -> 6
n %= 4;   // n = n % 4  -> 2
n **= 3;  // n = n ** 3 -> 8

// Logical assignment (ES2021)
let a = null;
a ??= "default";  // assign only if null or undefined
console.log(a);   // "default"

let b = 0;
b ||= 42;         // assign if left side is falsy
console.log(b);   // 42

let c = 1;
c &&= 99;         // assign if left side is truthy
console.log(c);   // 99

Comparison Operators

Comparisons return true or false. The critical rule: always use === (strict), never == (loose).

JavaScript
// Strict equality (===) - checks value AND type
console.log(5 === 5);       // true
console.log(5 === "5");     // false - different types
console.log(null === null); // true

// Strict inequality (!==)
console.log(5 !== "5");     // true
console.log(5 !== 5);       // false

// Relational
console.log(5 > 3);        // true
console.log(5 >= 5);       // true
console.log(3 < 5);        // true
console.log(3 <= 2);       // false

// String comparison (lexicographic)
console.log("banana" > "apple"); // true (b > a)
console.log("10" > "9");         // false! ("1" < "9" lexicographically)
console.log(10 > 9);             // true (numeric)

// Loose equality == - avoid!
console.log(0   == false);  // true  (coerces false to 0)
console.log("" == false);   // true  (both coerce to 0)
console.log(null == undefined); // true (special case)
console.log(null == false);     // false (null only == undefined)
console.log(NaN == NaN);        // false (NaN never equals anything)

Logical Operators

&&, ||, and ! are the three logical operators. Importantly, && and || do not return true/false - they return one of their operands.

JavaScript
// && (AND) - returns first falsy value, or last value if all truthy
console.log(true && true);    // true
console.log(true && false);   // false
console.log(1 && 2);          // 2  (1 is truthy, so return last: 2)
console.log(0 && 2);          // 0  (0 is falsy, short-circuit here)
console.log("a" && "b");      // "b"

// || (OR) - returns first truthy value, or last value if all falsy
console.log(false || true);   // true
console.log(0 || 42);         // 42 (0 is falsy, return next: 42)
console.log("" || "default"); // "default"
console.log("hello" || "x");  // "hello" (first truthy wins)

// ! (NOT) - converts to boolean and inverts
console.log(!true);           // false
console.log(!0);              // true
console.log(!"");             // true
console.log(!"hello");        // false
console.log(!!0);             // false (double NOT = boolean cast)
console.log(!!"text");        // true

// Short-circuit evaluation
const user = null;
user && console.log(user.name); // safe - right side never runs

const port = process.env.PORT || 3000; // common default pattern
Short-Circuit for Defaults

A classic pattern: const name = inputName || "Guest" uses short-circuit to provide a default. The caveat: || treats 0, "", and false as falsy too. If those are valid values, use ?? instead: const count = inputCount ?? 0.

Nullish Coalescing (??)

The ?? operator returns the right-hand side only when the left side is null or undefined - not for 0, false, or empty string.

JavaScript
// ?? vs || comparison
const a = 0;
console.log(a || 10);  // 10  (|| treats 0 as falsy - may not be intended)
console.log(a ?? 10);  // 0   (?? only triggers for null/undefined)

const b = "";
console.log(b || "default"); // "default" (|| treats "" as falsy)
console.log(b ?? "default"); // ""        (?? keeps empty string)

const c = null;
console.log(c ?? "fallback"); // "fallback"

const d = undefined;
console.log(d ?? "fallback"); // "fallback"

// Practical use: user settings where 0 is valid
function getTimeout(config) {
    return config.timeout ?? 5000; // 0ms timeout is valid, do not replace with 5000
}

// Nullish assignment ??= (ES2021)
let settings = { theme: null };
settings.theme ??= "light"; // only sets if null or undefined
console.log(settings.theme); // "light"

Optional Chaining (?.)

The ?. operator short-circuits to undefined if the left side is null or undefined, instead of throwing a TypeError.

JavaScript
const user = {
    name: "Alice",
    address: {
        city: "London"
    }
};

// Without optional chaining - crashes if address is missing
// const city = user.location.city; // TypeError!

// With optional chaining
console.log(user?.address?.city);    // "London"
console.log(user?.phone?.number);    // undefined (no crash)

// Optional chaining with methods
const arr = null;
console.log(arr?.map(x => x * 2));  // undefined (no crash)

// Optional chaining with bracket notation
const key = "name";
console.log(user?.[key]);            // "Alice"

// Combine with ?? for a default
const city = user?.address?.city ?? "Unknown";
console.log(city); // "London"

const phone = user?.phone?.number ?? "No phone";
console.log(phone); // "No phone"

Ternary Operator

The ternary operator is a compact alternative to if/else for simple conditional expressions. Syntax: condition ? valueIfTrue : valueIfFalse

JavaScript
const age = 20;

// Basic ternary
const status = age >= 18 ? "adult" : "minor";
console.log(status); // "adult"

// Equivalent if/else
let status2;
if (age >= 18) {
    status2 = "adult";
} else {
    status2 = "minor";
}

// Ternary in template literals
const name = "Alice";
console.log(`Hello, ${name ? name : "Guest"}!`); // "Hello, Alice!"

// Nested ternary - use sparingly (hard to read)
const score = 75;
const grade = score >= 90 ? "A"
            : score >= 80 ? "B"
            : score >= 70 ? "C"
            : "F";
console.log(grade); // "C"

// Better: use if/else or a lookup object for complex cases

Operator Precedence

When multiple operators appear in one expression, JavaScript evaluates them in order of precedence (highest first). When in doubt, use parentheses.

PriorityOperatorsExample
Highest()(2 + 3) * 4
High**2 ** 3 = 8
High* / %3 * 4 / 2
Mid+ -3 + 4 - 1
Mid< > <= >=a > b
Mid=== !== == !=a === b
Low&&a && b
Low||a || b
Low??a ?? b
Lowest= += -= etc.assignment
JavaScript
// Precedence in action
console.log(2 + 3 * 4);    // 14 (not 20 - * before +)
console.log((2 + 3) * 4);  // 20 - parentheses override

console.log(true || false && false); // true (&& before ||)
// reads as: true || (false && false) -> true || false -> true

// When mixing && and ||, be explicit with parentheses
const a = true, b = false, c = true;
const result = (a || b) && c; // clear intent

Frequently Asked Questions

== (loose equality) converts both values to a common type before comparing. === (strict equality) compares both value AND type with no conversion. Always use ===. Examples: "5" == 5 is true but "5" === 5 is false. The only common exception: value == null checks for both null and undefined at once.

The nullish coalescing operator ?? returns the right-hand value only when the left side is null or undefined. Unlike || which treats all falsy values (0, "", false) as fallbacks, ?? only triggers for null/undefined. Use it when 0 or empty string are valid values you want to keep.

Logical operators && and || do not always evaluate both sides. With &&: if the left side is falsy, the right side is never evaluated. With ||: if the left side is truthy, the right side is never evaluated. This is used for conditional execution: isLoggedIn && showDashboard() calls the function only if logged in.

Optional chaining ?. safely accesses nested object properties without throwing a TypeError if an intermediate value is null or undefined. Instead of throwing, it short-circuits and returns undefined. Example: user?.address?.city returns undefined if user or address is null, instead of crashing.