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);
}
}