Consider the following piece of code:
function A()
{
for(i = 0; i < 3; i++)
{
console.log("---" + i + "---");
B();
}
}
function B()
{
for(i = 0; i < 3; i++)
{
console.log(i);
}
}
A();
Expected Output:
---0---
0
1
2
---1---
0
1
2
---2---
0
1
2
Received Output:
---0---
0
1
2
I've used a for loop as described here. This is the first result when searching for "javascript for loop" with Google. And dozens of examples are found that suggest a similar approach.
Quote from www.w3schools.com:
for (i = 0; i < cars.length; i++) {
text += cars[i] + "<br>";
}
Why does 'A()
' not deliver the expected output?
Note:
I am posting this question because I encountered this problem and didn't find anything on the web about this issue despite that the chance of encountering it is relatively high.
In Javascript variables that are set but weren't declared beforehand
are created in the global scope.
This is fine in most of the cases but since 'i
' is often the number one chooses when needing a name for a counter variable this can become a serious issue.
If some for loops are nested of course you would use 'j
', 'k
', 'l
', ...
as counter variable names to not interfere with the iterations of other for loops, but when calling a function 'X()
' inside a for loop, especially when you aren't the author of 'X()
', for loops using the same counter variable names will interfere with each other.
This means you should really declare any counter variable in local scope to avoid such issues, which can be pretty hard to debug if you don't know what you are looking for.
Now let's have a look what happens when calling 'A()
' from the question.
function A()
{
for(i = 0; i < 3; i++)
{
console.log("---" + i + "---");
B();
}
}
The following steps are performed before executing 'B()
':
- The for loop is entered and '
i
' is set to '0
'.
- Since '
0 < 3
' is true
the loop body will be entered.
- '
---0---
' is printed to the console.
Now 'B()
' is called.
function B()
{
for(i = 0; i < 3; i++)
{
console.log(i);
}
}
The following steps are performed before 'B()
' finishes execution:
- The for loop is entered and '
i
' is set to '0
'.
- Since '
0 < 3
' is true
the loop body will be entered.
- '
0
' is printed to the console.
- '
i
' is incremented by '1
' and now holds the value '1
'.
- Now the loop repeats '
2.
to 4.
' but with ever increasing value of 'i
':
'1
' and '2
' are printed to the console.
- Since '
3 < 3
' is false
the for loop and with it 'B()
' finishes execution.
Now we are back in 'A()
' but 'i
' has a value of '3
':
function A()
{
for(i = 0; i < 3; i++)
{
console.log("---" + i + "---");
B();
}
}
Then there are only two additional steps performed:
- '
i
' is incremented by '1
' and now holds the value '4
'.
- Since '
4 < 3
' is false
the for loop and with it 'A()
' finishes execution.
So the example from the question should therefore be changed from:
for (i = 0; i < 3; i++) {
//...
}
to
for (var i = 0; i < 3; i++) {
//...
}
or
var i;
for (i = 0; i < 3; i++) {
//...
}