Identifiers of both, variable and function declarations (and also formal parameters for function code) are made when entering the execution context, that's actually before the code execution.
In the case of variables, as you noted it, they are initialized with the undefined value at that stage, the assignment takes places after, when control reaches the assignment expression, e.g.:
var foo = "outer";
(function () {
alert(foo); // undefined
var foo = "inner";
})();
In the above code, we can see how the foo identifier holds the undefined value, that's because when entering the function execution context, the local foo variable was initialized.
That's one of the reasons why people recommend to declare your variables at the top of the function (to resemble what actually happens)
Functions declarations are also hoisted, you can actually use them before its declaration, because as we know, it was made before the code execution, for example:
func(); // "bar"
function func () {
return "bar";
}
See also: