Variables, types, and control flow
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 —
trueorfalse - 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.