What the code is supposed to do
This program mixes lines that run once with lines that run for every student. The expected output is:
What a nice day!
Hey, Andy
How are you?
Hey, Mike
How are you?
Hey, Mary
How are you?
Let's start the class!
So What a nice day! opens the output once, each student gets a greeting followed by How are you?, and Let's start the class! closes it once. The starting code has every one of those lines in the wrong place:
const students: string[] = ["Andy", "Mike", "Mary"];
console.log("Let's start the class!");
for (const student of students) {
console.log("What a nice day!");
}
console.log("How are you?");
console.log("Hey, " + student);
What goes wrong
The program runs from top to bottom, so tracing it shows three separate problems:
- The closing line comes first.
Let's start the class!is above the loop, so it prints before anything else. - The opening line is in the loop.
What a nice day!is inside the braces, so it prints three times, once per student. - The per-student lines are outside the loop.
How are you?would print once, and the last line usesstudentafter the loop has ended. That variable exists only inside the loop body, so the program stops there withReferenceError: student is not defined. The compiler also reportsCannot find name 'student'.
The run therefore prints Let's start the class!, then What a nice day! three times and How are you?, and then fails on the last line. This is the exact output you get from the starting code, apart from the error text.
Fixing it step by step
Decide for each of the four messages how often it should happen, and place it accordingly:
What a nice day!happens once, at the start. Put it before the loop.Hey,plus the name happens once per student. Put it inside the loop body, wherestudentexists.How are you?follows each greeting, so it happens once per student too. Put it in the body, directly after the greeting.Let's start the class!happens once, at the end. Put it after the closing brace.
The fixed code in TypeScript
const students: string[] = ["Andy", "Mike", "Mary"];
console.log("What a nice day!");
for (const student of students) {
console.log("Hey, " + student);
console.log("How are you?");
}
console.log("Let's start the class!");
The output matches the expected lines. The structure is the same one seen in every loop: a beginning that runs once, a body that runs once for each element, and an end that runs once.
The order of the two statements inside the body matters too. With the greeting first, each student's pair of lines reads as Hey, Andy and then How are you?. Swapping them would print the question before the greeting.
Why the variable is out of reach
A variable declared in a loop header, such as student, lives only inside the loop. This is called its scope. Outside the braces there is no student, even though the loop used it a moment earlier, and there would be no single value for it to hold anyway: it takes three different values over the three passes.
If you ever want to print something about every student, the statement has to be in the body. If you want to use a result after the loop, you need a variable declared before it, which later lessons cover.
Common mistakes
- Fixing the order but not the loop. Moving the closing message to the end is not enough if
What a nice day!is still in the body. - Leaving the error line outside. The
ReferenceErrorgoes away only when the greeting is inside the braces. - Printing
How are you?once at the end. The expected output asks it after every student. - Not tracing the result. Count the lines: eight in total, of which two appear once and six come from the three passes.
Checking your fix
Run the code in the editor above and compare line by line. Lines 1 and 8 are the one-time messages, and lines 2 to 7 are the three pairs.