MDN says that "A function declaration is also limited in scope inside the block where the declaration occurs" (link) and shows an example:
foo('outside'); // TypeError: foo is not a function
{
function foo(location) {
console.log('foo is called ' + location);
}
foo('inside'); // works correctly and logs 'foo is called inside'
}
So far so good, but if we call function under its declaration:
{
function foo(location) {
console.log('foo is called ' + location);
}
foo('inside'); // works correctly and logs 'foo is called inside'
}
foo('outside'); // 'foo is called outside'
Suddenly function is no longer block scope, but rather function scope. It behaves exactly like var, which is function scope:
console.log(typeof foo);//undefined
{
var foo = function(location) {
console.log('foo is called ' + location);
}
console.log(typeof foo);//function
}
console.log(typeof foo);//function
My question is: what is the scope of function? And if its scope is function what's wrong with hoisting? Or is it correct implementation, but I don't understand something correctly?
Because of some confusion I have created below examples: 1 everything is fine
foo();//logs 'bar' because of hoisting
function foo(){
console.log('bar');
}
1b everything is fine, function expressions aren't hoisted
foo();//Error! foo is declared, so it was hoisted, but without its body, so it cannot be called
var foo = function(){
console.log('bar');
}
2 This one causes confusion. If functions scope is function, then why below function declaration is not hoisted? For some strange reason it is working like 1b (function expression, not function declaration)
foo();//Error! foo is declared, so it was hoisted, but without its body, so it cannot be called
{
function foo(){
console.log('bar');
}
}
3 If function scope is block, then why function is available outside of the block?
{
function foo(){
console.log('bar');
}
}
foo();//logs 'bar'
3b everything is fine. Let scope is block, so it's unavailable outside of block
{
let foo = function(){
console.log('bar');
}
}
foo();//Error, not declared