Operators

Difficulty: Beginner

Operators are symbols that tell the JavaScript engine to perform specific mathematical, relational, or logical computations. They take one or more values (operands), perform an operation, and produce a result. Understanding operators thoroughly is essential because they appear in virtually every line of JavaScript code you will write.

Arithmetic operators perform mathematical calculations. The standard ones are addition (+), subtraction (-), multiplication (*), division (/), and modulus/remainder (%). ES2016 added the exponentiation operator (). The addition operator is special because it doubles as the string concatenation operator - when either operand is a string, JavaScript converts the other operand to a string and concatenates them. The increment (++) and decrement (--) operators add or subtract 1, and their prefix vs postfix forms behave differently.

Comparison operators compare two values and return a boolean. JavaScript has two sets: loose equality (== and !=) which perform type coercion before comparing, and strict equality (=== and !==) which compare both value and type without coercion. The relational operators (<, >, <=, >=) compare values in order. Always prefer strict equality (===) over loose equality (==) to avoid unexpected type coercion bugs.

Logical operators work with boolean values. AND (&&) returns the first falsy value or the last value if all are truthy. OR (||) returns the first truthy value or the last value if all are falsy. NOT (!) negates a boolean value. These operators use short-circuit evaluation, meaning they stop evaluating as soon as the result is determined. This behavior is commonly used for conditional execution and providing default values.

The ternary operator (condition ? valueIfTrue : valueIfFalse) is the only JavaScript operator that takes three operands. It provides a concise alternative to simple if/else statements and is especially useful in template literals and JSX. The nullish coalescing operator (??) was added in ES2020 and returns the right-hand operand only when the left-hand operand is null or undefined - unlike ||, which triggers on any falsy value including 0, empty string, and false.

Operator precedence determines the order in which operators are evaluated when multiple operators appear in a single expression. Multiplication and division have higher precedence than addition and subtraction, just like in mathematics. Parentheses always have the highest precedence and should be used liberally to make your intent clear. The assignment operators (=, +=, -=, *=, /=, %=, =) have very low precedence, ensuring the right side is fully evaluated before the result is assigned.

Code examples

Arithmetic Operators

console.log(10 + 3);   // Addition
console.log(10 - 3);   // Subtraction
console.log(10 * 3);   // Multiplication
console.log(10 / 3);   // Division (floating point)
console.log(10 % 3);   // Modulus (remainder)
console.log(2  10);  // Exponentiation

// The + operator with strings
console.log("Hello" + " " + "World");
console.log("Age: " + 25);
console.log(5 + 3 + " items");
console.log("Total: " + 5 + 3);

// Increment and Decrement
let a = 5;
console.log(a++); // 5 (returns then increments)
console.log(a);   // 6
console.log(++a); // 7 (increments then returns)

Notice the tricky behavior of + with strings: '5 + 3 + " items"' evaluates left to right, so 5+3=8 first, then 8+" items"="8 items". But '"Total: " + 5 + 3' concatenates because the first operand is a string, resulting in "Total: 53" instead of "Total: 8".

Comparison Operators: == vs ===

// Strict equality (===) - no type coercion
console.log(5 === 5);       // true
console.log(5 === "5");     // false
console.log(null === undefined); // false

// Loose equality (==) - performs type coercion
console.log(5 == "5");      // true (string coerced to number)
console.log(null == undefined); // true (special rule)
console.log(0 == false);    // true
console.log("" == false);   // true
console.log(0 == "");       // true

// Relational operators
console.log(10 > 5);       // true
console.log("apple" < "banana"); // true (lexicographic)
console.log("10" > "9");   // false (string comparison: "1" < "9")

Strict equality (===) checks both type and value - use this by default. Loose equality (==) converts types before comparing, leading to surprising results like 0 == '' being true. String comparison is lexicographic (character by character), so '10' < '9' because '1' comes before '9'.

Logical Operators and Short-Circuit Evaluation

// AND (&&) - returns first falsy or last value
console.log(true && "hello");   // "hello"
console.log(false && "hello");  // false
console.log(1 && 2 && 3);      // 3
console.log(1 && 0 && 3);      // 0

// OR (||) - returns first truthy or last value
console.log(false || "hello");  // "hello"
console.log("" || "default");   // "default"
console.log(0 || null || "hi"); // "hi"
console.log("a" || "b");        // "a"

// NOT (!) - negates
console.log(!true);    // false
console.log(!0);       // true
console.log(!!"");     // false (double NOT for boolean conversion)
console.log(!!"text"); // true

&& and || don't just return true/false - they return one of their operands. && returns the first falsy value it encounters, or the last value if all are truthy. || returns the first truthy value, or the last value if all are falsy. Double NOT (!!) converts any value to its boolean equivalent.

Nullish Coalescing (??) vs OR (||)

// OR (||) triggers on ANY falsy value
console.log(0 || "default");       // "default" (0 is falsy)
console.log("" || "default");      // "default" ("" is falsy)
console.log(false || "default");   // "default"
console.log(null || "default");    // "default"

// Nullish coalescing (??) triggers ONLY on null/undefined
console.log(0 ?? "default");       // 0 (0 is not null/undefined)
console.log("" ?? "default");      // "" ("" is not null/undefined)
console.log(false ?? "default");   // false
console.log(null ?? "default");    // "default"
console.log(undefined ?? "default"); // "default"

// Practical example: user settings
const userVolume = 0; // User intentionally set volume to 0
const volumeWithOR = userVolume || 50;   // 50 (wrong!)
const volumeWithNC = userVolume ?? 50;   // 0 (correct!)
console.log(volumeWithOR, volumeWithNC);

The nullish coalescing operator (??) is purpose-built for providing defaults only when a value is null or undefined. This is better than || for cases where 0, empty string, or false are legitimate values that should not be replaced with a default.

Key points

Concepts covered

Arithmetic Operators, Comparison Operators, Logical Operators, Ternary Operator, Nullish Coalescing, Operator Precedence