The for Loop
In short: for (init; condition; step) runs three gates in a fixed
order: init once, before the loop starts at all; condition, checked
before every lap, including the very first; and step, run after
the body, at the end of every lap. When the condition is false, the loop
stops without running the body again. This is the classic way to walk an
array by index — and the off-by-one mistake it invites is the most common
loop bug in any language.

Numbering a playlist
The everyday job: print every song with its position.
i starts at 0 (gate 1, once), the loop keeps going while i < songs.length
(gate 2, checked before each lap), and i++ moves to the next index after
each song prints (gate 3). Three songs, three laps, done.
Reading one past the end
Swap < for <= and the loop runs one lap too many:
Arrays are indexed from 0, so the last valid index is songs.length - 1.
i <= songs.length lets i reach songs.length itself — one past the
end — and songs[3] on a 3-item array is undefined, not an error.
condition runs before every lap, with no exception for the last one, so
nothing warns you; the extra lap just happens.
A running total, and where i lives
for is just as useful without touching an array at all — and the
variable it declares belongs to the loop, not to the code around it:
total adds 0 + 1 + 2 + 3 + 4, giving 10. i, declared with let
inside the parentheses, is scoped to the loop — asking for it afterwards
behaves exactly like asking for a name that was never declared.
Quick practice
for (let i = 0; i < 4; i++) { console.log(i); } — how many times does it print, and what is the last value?
What does for (let i = 10; i > 0; i -= 2) { console.log(i); } print on its first two laps?
Why does for (let i = 0; i <= songs.length; i++) console.log(songs[i]); print an extra undefined?
