This is because variables in JavaScript are scoped to functions (or the global scope if not within a function). A var
is not scoped inside of a loop, and curly braces do not defined a new closure. Basically, the value of j
persists after the loop body, and the var
does not re-define j
as undefined
. This is why explicitly setting var j = null;
has the expected effect.
Example 1:
A good way to think about this is, any time you declare a variable with var
, like this.
function someFunc() {
for(var i = 0; i < 3; i++){
var j;
}
}
The interpreter hoist the variable declarations like so.
function someFunc() {
var i;
var j;
for(i = 0; i < 3; i++){
}
}
Notice that since the var j
declaration is hoisted to the top of the function, the declaration actually does nothing within the loop.
Example 2:
However, if you were to initialize the variable with null
like this.
function someFunc() {
for(var i = 0; i < 3; i++){
var j = null;
}
}
It would be interpreted like this.
function someFunc() {
var i;
var j;
for(i = 0; i < 3; i++){
j = null;
}
}
Notice how for every loop, j
is set to null
.
ES6 let keyword:
There is a keyword in ES6 which will create a scope in a loop like this, it is the let
keyword. Keep in mind that browser support for the let
keyword is poor at this point.
for (var i = 1; i < 3; i++) {
let j;
if (!j) {
j = 1;
} else {
alert("why are we here? j shouldn't be defined but it's "+ j);
}
}