foo is going to be null - foo is going to be undefined in your case, because the variable will be hoisted.
ES5 is function scoped and not block scoped, meaning the following code:
function foo() {
if (true) {
var bar = 'Hello World';
}
return bar;
}
foo();
will output Hello World. What is actually happening? - Before executing the above code, the variables and functions are stored in memory. They are not physically moved at the top of the function! This means that before execution, the body of the function foo and the variable bar, without its value will be stored in memory. This is what hoisting actually does.
When the execution of the code starts, the JavaScript interpreter already has access to foo() and bar (bar is assigned the value of undefined). When the execution reaches line 3 - var bar = 'Hello World'; , JavaScript simply assigns a new value to the variable bar - in our case the right side of the assignment - Hello World. At first it seems that var bar = 'Hello World'; is one statement, but are actually two separate statements - var bar; and bar = 'Hello World' .
Let's transform our example to ES6:
function foo() {
if (true) {
const bar = 'Hello World';
}
return bar;
}
foo();
This code will throw with a ReferenceError - ReferenceError: bar is not defined . This is because const and let , the two new variable types is ES6, are block scoped.
Block statement, also known as compound statement is a group of zero or more statements, wrapped in curly brackets:
{ } // empty block statement
{
const message = 1;
} // non empty block statement
So, if we have the following code:
const exam = 'passed';
if (true) {
const exam = 'failed';
}
console.log(exam); // 'passed'
The output will be passed, because the code has two scopes - the "global" scope, where the variable const exam = 'passed' lives and the block scope, where the variable exam is assigned the value failed . Although looking pretty similar, they are two distinct variables.
So, my rule of thumb is to use const whenever possible, let if I need to change the value of the variable at a latter state and forget about var.
Variable initialization inside if statement is error prone and kind of makes me uncomfortable. Lets say you have a fairly big function, where you assign a value to a variable, forget about it and reassign it again in an if statement. The chance of assigning the wrong value is very high. Another reason why I'm against this is because it hardens readability and debugging. My personal preference is to store all function variables at the top of the function, instead being spread across the whole function body.