From this source: Variable hoisting inside IIFE (lazy parsing)
The situation you are experimenting is related to the immutability/mutability of the identifier/name of a function
when it is a function expression (identifier inmutable) and a function declaration (identifier mutable).
In your first example, there is a function declaration with identifier a
(mutable), so you are overwriting it inside the method and the output is the result of that overwriting:
function a()
{
console.log("Without overwrite:", a);
a = 1; // The identifier `a` is mutable!
console.log("After overwrite:", a);
}
a();
.as-console {background-color:black !important; color:lime;}
.as-console-wrapper {max-height:100% !important; top:0;}
On the second and third examples, you are using function expressions where the identifier a
is not mutable (i.e, read-only). So, you can't change it and the output of the console is the function definition:
(function a()
{
a = 1; // The identifier `a` is not mutable!
console.log(a);
})();
var b = function aa()
{
aa = 1; // The identifier `aa` is not mutable!
console.log(aa);
}
b();
.as-console {background-color:black !important; color:lime;}
.as-console-wrapper {max-height:100% !important; top:0;}