What the code is supposed to do
The function printSum takes an array of numbers, nums, and should print the sum of all of them, once. Called with [1, 2, 3] it should print 6, because 1 + 2 + 3 = 6. Instead, the code you start with prints three lines:
1
2
3
Here is that code. The call on the last line must stay exactly as it is:
function printSum(nums: number[]): void {
for (const num of nums) {
let sum: number = 0;
sum += num;
console.log(sum);
}
}
// Do not change this code:
printSum([1, 2, 3]);
There are two mistakes. Each one hides the other: fix only one and the output is still wrong.
What goes wrong
Trace the loop by hand. The body runs once for each number, and each run does the same three things.
- The first pass,
num = 1.let sum: number = 0creates a new variable holding 0. Thensum += nummakes it 1, andconsole.log(sum)prints1. - The second pass,
num = 2. A brand-newsumis created, again holding 0. After the addition it is 2, and2is printed. - The third pass,
num = 3. The same thing happens, and3is printed.
The two mistakes are visible in that trace:
- The total is declared inside the loop. A variable declared in a loop body is created again on every pass and disappears at the end of it. Nothing carries over from one number to the next, so
sumnever holds more than one number's worth. - The print is inside the loop.
console.log(sum)runs once per number. The total isn't complete until the last number has been added, so the print belongs after the loop.
Why fixing only one is not enough
Move let sum: number = 0 above the loop but leave the print inside it, and sum does accumulate. The function then prints a running total: 1, 3, 6. The last line is right, but the first two are extra output.
Move only the print below the loop and the compiler reports Cannot find name 'sum', because the variable lives only inside the loop body, and that code still reaches the print. Even when the JavaScript runs anyway, it fails there, because no sum exists outside the loop.
Fixing it step by step
- Move the declaration above the loop.
let sum: number = 0now runs once, before the first number is looked at. It is declared withletand notconst, because the loop changes it. - Leave the addition in the loop.
sum += numadds the current number to the total, and the total now survives from one pass to the next. - Move the print below the loop. When the loop ends, every number has been added, and one
console.log(sum)prints the finished total. - Leave the call alone.
printSum([1, 2, 3])is unchanged.
The fixed code in TypeScript
function printSum(nums: number[]): void {
let sum: number = 0;
for (const num of nums) {
sum += num;
}
console.log(sum);
}
printSum([1, 2, 3]);
This prints 6. The details worth knowing:
- Scope. A
letvariable exists only inside the nearest pair of braces. That is why a declaration in the loop body is fresh on each pass, and why the fixed version has to declaresumoutside the loop to use it after the loop. const numis fine. In afor...ofloop each pass gets its ownnumthat is never reassigned, soconstworks.sumdoes change, so it needslet.- The
voidreturn type. The function prints and returns nothing, so its type isvoid. Like every annotation, it is erased when the code is compiled to JavaScript. - Printing, not returning. This function prints the total; it does not give it back to the caller. A function that returned the sum would end with
return sum;instead ofconsole.log(sum);.
Common mistakes
- Printing inside the loop. It gives one line per number, either the numbers themselves or a running total.
- Declaring the total in the loop. It resets to 0 on every pass.
- Starting the total at something other than 0. The sum would then be off by that starting value.
- Using
=instead of+=.sum = numkeeps only the last number, so the output would be3. - An empty array. The loop never runs, and the fixed function prints
0, the sum of nothing.
Checking your fix
Run the code in the editor above. A correct fix prints a single line, 6. If you see 1, 3, 6 on three lines, the print is still inside the loop. If you see 1, 2, 3, the declaration is still inside it.