What the code is supposed to do
The program has an array of foods and should print I'm hungry! one time, and after it one line for each food: I'll eat some pasta, I'll eat some burgers and I'll eat some pizza. The code you start with prints the hungry message again before every food:
let foods: string[] = ["pasta", "burgers", "pizza"];
for (let food of foods) {
console.log("I'm hungry!");
console.log("I'll eat some " + food);
}
I'm hungry!
I'll eat some pasta
I'm hungry!
I'll eat some burgers
I'm hungry!
I'll eat some pizza
Nothing here crashes and no error is reported. The program does exactly what its code says, and the code says something different from what was intended.
What goes wrong
The curly braces after for (let food of foods) mark the loop body, and every statement inside runs once per element. The array has three foods, so the body runs three times. Both console.log calls are inside the braces, which means both are printed three times, one after the other.
You can follow the flow pass by pass:
- Pass 1,
foodis"pasta": print the hungry message, then the pasta line. - Pass 2,
foodis"burgers": print the hungry message again, then the burgers line. - Pass 3,
foodis"pizza": the same again, with the pizza line.
The hungry message does not use food. It is the same text on every pass, and that is a sign it does not belong in the loop. A statement belongs in the body only if it must happen for each element.
Fixing it step by step
- Sort the statements into two kinds.
I'm hungry!is a one-time announcement.I'll eat some ...depends on the current food and must repeat. - Move the announcement above the loop. Code before the loop runs once, before the first pass, which also gives the order the expected output needs: the announcement first, the foods after it.
- Leave the second
console.login the body. It is already correct.
The fixed code in TypeScript
let foods: string[] = ["pasta", "burgers", "pizza"];
console.log("I'm hungry!");
for (let food of foods) {
console.log("I'll eat some " + food);
}
The program now prints:
I'm hungry!
I'll eat some pasta
I'll eat some burgers
I'll eat some pizza
Two TypeScript details are worth noting. The apostrophe in I'm is safe because the string is written with double quotes; inside single quotes you would need to write \'. And "I'll eat some " + food joins two strings, so the space at the end of the first piece is what separates some from the food name.
Where a statement belongs
The rule for this lesson holds for every loop you write:
- Before the loop: it runs once, first. Use it for announcements and for setting things up.
- Inside the loop: it runs once per element. Use it for work that depends on the current element.
- After the loop: it runs once, when every pass is done. Use it for closing messages and summaries.
Moving a line between these three places changes the output, even though the line itself is identical.
Common mistakes
- Moving the line below the loop. The message would print once, but after all the foods, which is the wrong order.
- Deleting the message from the loop and forgetting to add it back. The foods print correctly, but the hungry line is missing.
- Moving the wrong line. Taking the food line out of the loop would reference
foodoutside the loop, where it does not exist, and the program would fail with aReferenceError.
Checking your fix
Run the code in the editor above. The output should have four lines, and I'm hungry! should appear on the first one only. If it still appears more than once, check which side of the loop's braces the line is on.