Chapter 5 of 28 · JavaScript for Beginners — Complete Free Tutorial

Operators & Expressions

Operators combine values into new values; any valid combination is an expression that produces a result. This chapter tours arithmetic, assignment, comparison, logical and nullish operators — plus the ternary and comma operators — and shows how to read precedence without memorising a wall of rules.

Arithmetic

console.log(7 + 2);    // → 9
console.log(7 - 2);    // → 5
console.log(7 * 2);    // → 14
console.log(7 / 2);    // → 3.5
console.log(7 % 2);    // → 1   (remainder — the modulo operator)
console.log(2 ** 5);   // → 32  (exponentiation)

The modulo is a hidden tool — it answers “is it divisible?” and drives cycling patterns:

console.log(10 % 3 === 0);   // → false
console.log(9 % 3 === 0);    // → true  (9 divides evenly by 3)

// even / odd test
n % 2 === 0   // even
n % 2 !== 0   // odd

// wrap around a list of 5 (index 0–4)
console.log(7 % 5);   // → 2

Assignment operators

let score = 0;
score += 5;    // → 5   (score = score + 5)
score -= 2;    // → 3
score *= 10;   // → 30
score **= 2;   // → 900
score %= 7;    // → 4   (900 % 7)

The same shorthand exists for *=, /=, **=, %=, &&= and ||=.

Comparison operators

OperatorQuestionExampleResult
=== / !==Strictly equal / not equal (value and type)'5' === 5false
== / !=Loose equality (coerces types)'5' == 5true
>, <, >=, <=Numeric/string ordering'b' > 'a'true

String comparison uses character codes — 'apple' < 'banana' compares letter by letter. Numbers always beat NaN in confusion: NaN === NaN is false; test with Number.isNaN(x). As covered last chapter: prefer strict === everywhere.

Logical operators

// AND — true only if BOTH sides are truthy
console.log(true && false);   // → false
console.log('hi' && 42);       // → 42   (returns the value, not true/false!)

// OR — first truthy value wins
console.log(null || 'default'); // → 'default'
console.log('name' || 'anon');  // → 'name'

// NOT — flips to boolean
console.log(!'');      // → true
console.log(!(5 > 3)); // → false

Key insight: logical operators return values, not just booleans. That powers two common idioms:

const name = inputName || 'Guest';           // fallback when falsy
const isAdult = age >= 18 && hasConsent;      // combined condition

&& short-circuiting for guard clauses

user && user.address && user.address.city
// stops at the first falsy value instead of throwing

Optional chaining (user?.address?.city) is the modern, safer spelling of this pattern — introduced properly in Objects & JSON and used throughout later chapters.

Nullish coalescing (??) — the smarter fallback

console.log(0 ?? 'ten');      // → 0     ✅ 0 is a real value
console.log('' ?? 'text');    // → ''    ✅ empty string kept
console.log(null ?? 'n/a');   // → 'n/a'
console.log(undefined ?? 'd'); // → 'd'
console.log(0 || 'ten');      // → 'ten' 😬 (OR treats 0 as missing)

Rule: || falls back on anything falsy; ?? falls back only on null/undefined. Use ?? for numbers, strings and booleans where 0 or '' are legitimate values.

Ternary operator

const age = 20;
const label = age >= 18 ? 'adult' : 'minor';
console.log(label);   // → 'adult'

condition ? whenTrue : whenFalse — perfect for one expression inside templates or JSX-style output; for multi-branch logic, an if/else reads better (see Control Flow).

typeof and the in / instanceof operators

typeof 'x'                     // → 'string'
'name' in { name: 'Asha' }     // → true   (key exists?)
new Date() instanceof Date     // → true   (object is of class?)

Precedence: read it like maths

Yes, * binds tighter than +, and ! binds tightly — but when unsure, use parentheses. (a && b) || c communicates intent and never needs a cheat sheet.

Common mistakes

  • = vs === — assignment in a condition (if (x = 5)) is always truthy; a classic bug.
  • Using || for defaults with 0 — quantity || 1 turns a valid 0 into 1; use ??.
  • Comparing floats — 0.1 + 0.2 === 0.3 fails; use a tolerance.
  • Deep ternary nests — a ? b : c ? d : e is unreadable; prefer if/else or a lookup table.

Practice checklist

  1. Write a isEven(n) one-liner using modulo.
  2. Build a grade function: score 90+ → 'A', 80+ → 'B', … using the ternary chain — then rewrite with if/else and compare readability.
  3. Demonstrate ?? vs || with the values 0, '' and null.

Expressions decide values — control flow decides paths. Next: Conditionals & Control Flow.

Quiz: Operators & Expressions

5 questions · 70% to pass

Frequently Asked Questions

JavaScript is the programming language of the web. It adds behaviour to pages: responding to clicks and input, validating forms, fetching data from APIs, updating the DOM without reloading, and much more. It also runs on servers (Node.js), in desktop and mobile apps, and in build tooling.

They are unrelated languages that share a similar name for historical marketing reasons. Java is a statically-typed compiled language; JavaScript is a dynamically-typed interpreted language designed for the browser. Knowing one does not imply knowledge of the other.

Helpful but not mandatory — HTML gives you the structure JavaScript manipulates and CSS the styling it toggles. If you know basic tags, classes and selectors, you have enough to start; the DOM chapters assume only that much.

Use const by default and let when the value must change. Avoid var entirely in modern code: it is function-scoped instead of block-scoped, hoists differently, and can create accidental globals. This course uses const and let throughout.

The Document Object Model is the browser’s in-memory tree of objects representing your HTML. JavaScript reads and modifies that tree — selecting elements, changing text, adding nodes, attaching event listeners — and the browser re-renders the page to match.

== compares after converting types (so 5 == "5" is true), while === requires the same value AND the same type (5 === "5" is false). Loose equality has famously confusing rules — use === and !== everywhere unless you have a specific reason not to.

JavaScript is single-threaded, so long-running work (timers, fetches, events) is handled by the browser and its callbacks are queued. The event loop moves queued callbacks onto the call stack only when it is empty, with promise callbacks (microtasks) taking priority over timers. It is why asynchronous code never freezes the page.

A Promise is an object representing a future value — pending, fulfilled or rejected — that can be chained and combined (Promise.all). async/await is syntax sugar over promises that lets asynchronous code read top-to-bottom with ordinary try/catch error handling.

Yes. Frameworks are built on exactly these fundamentals — components are functions, state is your variable discipline, effects are events, rendering is DOM work. Developers who learn vanilla first understand what the framework is doing and debug far faster.

Type out the examples instead of copying, build small end-to-end projects (expense tracker, weather app, quiz), handle every UI state (loading, empty, success, error), and revisit fundamentals while reading real code. Consistency beats volume — a little most days outpaces occasional marathons.