Foundations roadmap

Variables, types, and control flow

Log in to save this

Saving keeps this in your list across devices. It's a free account — no card.

Every program does two things over and over: it stores data, and it makes decisions about that data. Every language writes this differently, but the ideas — naming values, knowing what kind of value you have, branching, and repeating — are the same everywhere. This lesson uses JavaScript; pick one language and get genuinely comfortable here before moving on, because depth beats breadth this early.

Variables: naming a value

A variable is a name that points to a value, so you can use and change it later. In modern JavaScript you declare variables with const or let:

const name = "Ada";   // can't be reassigned
let score = 0;        // can be reassigned
score = score + 10;

Use const by default and let only when the value really needs to change. Trying to reassign a const throws a TypeError. You'll see var in older code; avoid it in new code.

Variables declared with let or const live inside the nearest pair of curly braces { }, called their block. A variable created inside an if block doesn't exist after that block ends, and using it outside gives a ReferenceError.

Good names say what the value means: itemCount beats x.

Types: what kind of value you have

Every value has a type, and the type decides what operations make sense. The common ones in JavaScript:

  • string — text: "hello"
  • number — integers and decimals: 42, 3.14
  • boolean — true or false
  • undefined — declared but no value given
  • null — deliberately "no value"
  • arrays and objects — collections: [1, 2, 3], { name: "Ada" }

typeof tells you what you have. JavaScript also converts types automatically in some operations, which surprises people:

"5" + 3   // "53"  (+ with a string joins text)
"5" * 2   // 10    (* converts to numbers)

Values from forms, URLs, and user input arrive as strings. Convert them with Number(value) before doing math.

Comparing values and truthiness

To compare, use === (strictly equal) and !== (not equal). These check type and value together, so "18" === 18 is false. The older == converts types first ("18" == 18 is true), which hides bugs, so prefer ===.

Conditions don't need to be booleans. JavaScript treats every value as "truthy" or "falsy" in an if. The falsy values are:

false  0  ""  null  undefined  NaN

(Plus the rarer -0 and 0n.) Everything else is truthy, including "0", "false", and empty arrays [].

This is handy (if (username) checks for a non-empty string), but it has a classic trap: 0 is falsy. If a score of zero is a real, valid score, if (score) will treat it as missing. Write the check you mean, like if (score !== undefined).

Making decisions with if / else

if runs code only when a condition is true. else if and else add more options:

if (temp > 30) {
  label = "hot";
} else if (temp > 20) {
  label = "warm";
} else {
  label = "cold";
}

JavaScript checks conditions top to bottom and runs only the first branch that matches, then skips the rest. Order therefore matters. If you put temp > 20 first, a temperature of 35 matches it and becomes "warm" — the "hot" branch is never reached. Put the most specific condition first.

Combine conditions with && (and), || (or), and ! (not): if (age >= 18 && hasTicket).

Repeating with loops

Loops run code many times. Three forms cover most needs:

for (let i = 0; i < items.length; i++) { /* by index */ }
for (const item of items) { /* each value */ }
while (attempts < 3) { attempts++; }

Array positions start at 0, so an array of 3 items has indexes 0, 1, and 2. A loop condition of i <= items.length runs one time too many and reads items[3], which is undefined. This is the famous off-by-one error. When you don't need the index, for...of avoids it entirely.

A while loop runs as long as its condition stays true. If nothing inside the loop changes the condition, it never ends — an infinite loop that freezes your program. Always make sure each pass moves toward stopping.

Try it: write a small grading program

Create grades.js and run it with node grades.js:

const scores = [92, 0, 67, 78, 85];
let passed = 0;

for (const score of scores) {
  if (score >= 90) {
    console.log(score, "A");
  } else if (score >= 70) {
    console.log(score, "Pass");
    passed++;
  } else {
    console.log(score, "Retry");
  }
}
console.log("Passed:", passed);

Before running it, predict every line of output. Then change it: count A grades as passed too, add a while loop that counts down from 3, and deliberately trigger a const reassignment error so you recognise it next time.