There's nothing unexpected in your code, it is behaving as it should.
console.log(i);
This log statement prints undefined because of a concept known as hoisting in javascript. When you define variables using var keyword, they are moved/hoisted to the top of the functional/local scope when javascript runs. 
Now you might ask that if variable declaration is moved/hoisted to the top of the functional/local scope then why does logging i prints undefined? That's because only variable declarations are hoisted to the top, not the value of the variable. So when you log i before the loop, it gives you undefined because Javascript recognizes that variable i exists in this scope but isn't given a value yet.
Inside for loop is where variable i is initialized to value 0 and then loop executes twice and gives you 0 and 1.
Now you can also access variable i after the for loop and that is because of functional scope of var. What this means is that variables defined with keyword var are available globally if not defined in any function.
If you don't want this behavior, use let instead of var. let keyword provides block level scope which means that variables defined using let keyword are only available in the block (between curly braces) in which they are defined.