🌱 Phase 1 · Foundations 🟢 Beginner MODULE 04

Operators

⏱️ 40 min read
📖 Theory + Code
🧩 5 Quiz Questions
🏗️ 1 Challenge
Your progress in Phase 128%
🎯 What you'll learn: All JavaScript operators — arithmetic, assignment, comparison, logical, ternary, nullish coalescing (??), optional chaining (?.), and how operator precedence determines evaluation order.

Arithmetic Operators

Arithmetic operators perform mathematical calculations. JavaScript supports all the standard math operators plus the powerful exponentiation (**) operator introduced in ES2016.

OperatorNameExampleResult
+Addition10 + 313
-Subtraction10 - 37
*Multiplication10 * 330
/Division10 / 33.333...
%Modulus (remainder)10 % 31
**Exponentiation ES201610 ** 31000
++Incrementx++ or ++xx + 1
--Decrementx-- or --xx - 1
arithmetic.js
JS
let a = 10, b = 3;

console.log(a + b);   // 13 — Addition
console.log(a - b);   // 7  — Subtraction
console.log(a * b);   // 30 — Multiplication
console.log(a / b);   // 3.333... — Division
console.log(a % b);   // 1  — Modulus (remainder)
console.log(a ** b);  // 1000 — Exponentiation (ES2016)

// Increment & 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

// Useful tricks with modulo
console.log(10 % 2 === 0); // true  — even number check
console.log(7 % 2 === 1);  // true  — odd number check
The modulo operator % is incredibly useful
Use % to check even/odd numbers, cycle through a fixed range of values (like wrapping around an array), implement clocks and timers, or test divisibility. Pattern: num % divisor === 0 means evenly divisible.

Assignment Operators

Assignment operators combine a mathematical operation with assignment into a single shorthand. They make code shorter and more readable.

assignment.js
JS
let score = 100;

score += 10;  // score = score + 10  → 110
score -= 5;   // score = score - 5   → 105
score *= 2;   // score = score * 2   → 210
score /= 3;   // score = score / 3   → 70
score %= 8;   // score = score % 8   → 6
score **= 2; // score = score ** 2  → 36

// String concatenation shorthand
let msg = "Hello";
msg += " World"; // msg = "Hello World"

// Logical assignment operators (ES2021)
let a2 = null;
a2 ??= "default"; // if null/undefined, assign "default"
console.log(a2);    // "default"

let b2 = 0;
b2 ||= 42; // if falsy, assign 42
console.log(b2); // 42  (0 is falsy)

let c2 = 5;
c2 &&= 10; // if truthy, assign 10
console.log(c2); // 10  (5 is truthy)

Comparison Operators

Comparison operators compare two values and return a boolean (true or false). The most important distinction in JavaScript is between loose equality (==) and strict equality (===).

comparison.js
JS
let x = 5, y = 10;

console.log(x == 5);    // true  — loose equality (type coercion!)
console.log(x === 5);   // true  — strict equality (NO coercion)
console.log(x != 10);   // true  — loose inequality
console.log(x !== y);   // true  — strict inequality
console.log(x > 3);     // true  — greater than
console.log(x < y);     // true  — less than
console.log(x >= 5);    // true  — greater than or equal
console.log(x <= 4);    // false — less than or equal

// ⚠️  The danger of == (loose equality / type coercion)
console.log(5 == "5");    // true  (coerces string "5" to number 5!)
console.log(5 === "5");   // false (different types — no coercion)
console.log(0 == false);  // true  (coerces boolean to 0!)
console.log(0 === false); // false (different types)
console.log(null == undefined);  // true  (special JS rule)
console.log(null === undefined); // false (different types)
⚠️
ALWAYS use === (triple equals) — never ==
The == operator does type coercion — it converts values before comparing, which causes subtle, hard-to-find bugs. 0 == false is true. "" == false is true. null == undefined is true. These are classic JavaScript traps. Use === always — it checks both value AND type.

Logical Operators

Logical operators combine boolean expressions. They also support short-circuit evaluation — a powerful pattern used everywhere in real JS code.

logical-operators.js
JS
// && (AND) — true only if BOTH sides are true
console.log(true && true);    // true
console.log(true && false);   // false
console.log(5 > 3 && 10 > 5); // true

// || (OR) — true if AT LEAST ONE side is true
console.log(false || true);   // true
console.log(false || false);  // false
console.log(5 > 10 || 5 > 3); // true

// ! (NOT) — inverts a boolean
console.log(!true);     // false
console.log(!false);    // true
console.log(!(5 > 3)); // false

// SHORT-CIRCUIT EVALUATION — key JS pattern!
// && returns the first FALSY value, or the last value
console.log(0 && "hello");    // 0      (falsy — stops early)
console.log(1 && "hello");    // "hello" (truthy — returns last)

// || returns the first TRUTHY value, or the last value
console.log(0 || "default");  // "default" (0 is falsy)
console.log("user" || "guest"); // "user"    (truthy — stops early)

// Real-world: default value pattern with ||
const username = null;
const displayName = username || "Guest"; // "Guest"
console.log(displayName);

Ternary Operator

The ternary operator is a one-line if/else expression. Syntax: condition ? valueIfTrue : valueIfFalse. It's perfect for simple conditional assignments and JSX in React.

ternary.js
JS
// Syntax: condition ? valueIfTrue : valueIfFalse

const age = 20;
const status = age >= 18 ? "Adult" : "Minor";
console.log(status); // "Adult"

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

// Real-world: UI state
const isLoggedIn = true;
const btnText = isLoggedIn ? "Logout" : "Login";
const welcome = `Hello, ${isLoggedIn ? "user" : "guest"}!`;
console.log(btnText);  // "Logout"
console.log(welcome);  // "Hello, user!"
Use ternary for simple conditions — if/else for complex logic
Ternary is great for simple assignments and inline JSX. If you find yourself nesting more than 2 levels, switch to an if/else block for readability. Readable code is better than clever code.

Nullish Coalescing Operator (??)

The ?? operator returns the right-hand side only when the left side is null or undefined. Unlike ||, it does NOT trigger for other falsy values like 0, "", or false.

nullish-coalescing.js
JS
// ?? vs || — the key difference
const userScore = 0;
console.log(userScore || 100);  // 100 (WRONG! 0 is falsy)
console.log(userScore ?? 100);  // 0   (correct — 0 is not null/undefined)

const username2 = null;
console.log(username2 ?? "Anonymous"); // "Anonymous" — null triggers ??

const count = undefined;
console.log(count ?? 0); // 0 — undefined triggers ??

// Real-world: handling API responses safely
const apiData = { name: "Alice", score: 0 };
const name3  = apiData.name  ?? "Unknown";  // "Alice"
const score3 = apiData.score ?? -1;         // 0 (not -1!)
console.log(name3, score3);  // "Alice" 0
Use ?? when 0, "", or false are valid values — use || for any falsy default
Rule of thumb: if 0, empty string, or false are meaningful values in your data, use ??. If you want any falsy value to fall back to a default, use ||. This distinction matters a lot when working with scores, counts, or boolean flags from APIs.

Optional Chaining (?.)

Optional chaining (?.) lets you safely access deeply nested object properties without throwing a TypeError when an intermediate value is null or undefined. It returns undefined instead of crashing.

optional-chaining.js
JS
const user = {
  name: "Alice",
  address: {
    city: "Karachi"
  }
};

// Without optional chaining — CRASHES if address is null
// console.log(user.profile.avatar); // TypeError: Cannot read properties of undefined!

// With optional chaining — returns undefined safely
console.log(user.address?.city);    // "Karachi"
console.log(user.profile?.avatar);  // undefined (no error!)
console.log(user.getName?.());      // undefined (method doesn't exist — no error!)

// Combine ?. with ?? for clean fallbacks
const city3 = user.address?.city ?? "Unknown city";
console.log(city3); // "Karachi"

const avatar = user.profile?.avatar ?? "default-avatar.png";
console.log(avatar); // "default-avatar.png"
🚀
?. + ?? is the power combo for API data
When working with API responses, you often have deeply nested data that might be missing. Combining ?. and ?? gives you safe access plus a clean fallback in one elegant expression: response?.user?.name ?? "Guest".

Operator Precedence

Just like in math (PEMDAS/BODMAS), JavaScript operators have a precedence order — higher precedence operators execute first. When in doubt, use parentheses.

precedence.js
JS
// Higher precedence executes first
console.log(2 + 3 * 4);   // 14  — * before + (like math!)
console.log((2 + 3) * 4); // 20  — parentheses first

// Precedence order (high → low, partial list):
// 1. ()          — Parentheses (highest)
// 2. **          — Exponentiation
// 3. * / %       — Multiplication, Division, Modulus
// 4. + -         — Addition, Subtraction
// 5. > < >= <=   — Comparison
// 6. === !== ==  — Equality
// 7. &&          — Logical AND
// 8. || ??       — Logical OR, Nullish Coalescing
// 9. ?:          — Ternary
// 10. = += -=    — Assignment (lowest)

// Real example — trace through step by step
const result = 2 + 3 > 4 && 10 !== 5;
// Step 1: 2 + 3 = 5          (+ before >)
// Step 2: 5 > 4 = true        (> before &&)
// Step 3: 10 !== 5 = true     (!== before &&)
// Step 4: true && true = true
console.log(result); // true

// Tricky: exponentiation is right-associative
console.log(2 ** 3 ** 2); // 512 — same as 2 ** (3 ** 2) = 2 ** 9
console.log((2 ** 3) ** 2); // 64  — use parens to force left-to-right
When in doubt, use parentheses
Parentheses make code readable AND ensure correct order. Never rely on memory of the full precedence table in complex expressions. Your future self (and teammates) will thank you for clear, explicitly-grouped expressions.

Summary

1
Arithmetic operators
+ - * / % ** for math. Use % for even/odd checks and cycling. Pre/post ++-- behave differently.
2
Always use === never ==
Strict equality checks both value AND type. Loose equality does type coercion and causes bugs. This is one of the most important JS rules.
3
Short-circuit evaluation
&& returns first falsy or last value. || returns first truthy or last value. These power default value patterns in real apps.
4
?? vs ||
Use ?? when 0, "", or false are valid values. Use || for any-falsy defaults. Combine ?. and ?? for safe API data access.
5
Operator precedence
* before +, comparison before equality, && before ||. When unsure — use parentheses.
🧩 Knowledge Check
5 questions — test your mastery of JavaScript Operators
1. What does the % (modulo) operator do?
2. What is the result of 5 == "5" in JavaScript?
3. What does the ?? (nullish coalescing) operator return?
4. What is the ternary operator syntax?
5. What does 2 + 3 * 4 evaluate to in JavaScript?
🏗️
Coding Challenge — Build a Grade Calculator
Apply all operators: arithmetic, comparison, logical, ternary, nullish coalescing
Task: Create gradeCalc.js. Given a student's test scores (at least 5), write code that:

1. Calculates the average score using arithmetic operators
2. Determines the letter grade using comparison and ternary: A (90+), B (80+), C (70+), D (60+), F (below 60)
3. Uses logical operators to check: isHonorRoll (average >= 90 && attendance >= 90), isPassing (average >= 60)
4. Uses ?? to handle missing attendance data (default to 100 if null)
5. Logs a full report using template literals
💡 Show hints
  • Sum all scores first, then divide by count for the average
  • Use nested ternary for grade OR if/else (your choice for readability)
  • Attendance might be null — use const att = rawAttendance ?? 100
  • isHonorRoll: avg >= 90 && att >= 90
  • Use a template literal for the final report card
gradeCalc.js — Sample Solution
JS
// ── Grade Calculator ─────────────────────────────
const scores = [85, 92, 78, 96, 88];
const rawAttendance = null;  // simulating missing API data

// 1. Calculate average using arithmetic operators
const total = scores.reduce((sum, s) => sum + s, 0);
const avg = total / scores.length;

// 2. Letter grade using ternary operators
const grade = avg >= 90 ? "A"
            : avg >= 80 ? "B"
            : avg >= 70 ? "C"
            : avg >= 60 ? "D"
            : "F";

// 4. Handle missing attendance with nullish coalescing
const attendance = rawAttendance ?? 100;  // null → 100%

// 3. Logical operator checks
const isPassing   = avg >= 60;
const isHonorRoll = avg >= 90 && attendance >= 90;

// 5. Full report with template literals
console.log(`
╔══════════════════════════╗
  Student Report Card
  ─────────────────────
  Scores     : ${scores.join(", ")}
  Average    : ${avg.toFixed(1)}%
  Grade      : ${grade}
  Attendance : ${attendance}%
  Passing    : ${isPassing ? "✓ Yes" : "✗ No"}
  Honor Roll : ${isHonorRoll ? "✓ Yes" : "✗ Not yet"}
╚══════════════════════════╝`);
Finished this lesson?
Mark it complete to track your progress.
🎉
Lesson 4 Complete!
You now know all of JavaScript's operators — the building blocks of every program logic.
← Course Home
Phase 1 · FoundationsLesson 4 of 7