0

So yes, this is something you don't wanna do practically, you always wanna avoid using the same name for different functions + you don't wanna be using var anymore for declaring variables because that can cause a lot of problems but I'm curious why does this happen!

We know variables declared with the keyword var and function declaration is hoisted to the top of their function scope in the creation phase, lets see an example of a variable first:

function f(){

console.log(p) // undefined

  if(true){
    var p = true;
  }
}

f()

We got undefined since we declared a variable inside an if block and since if doesnt get their own execution context, the variable we declared is hoisted to the top something like this:

function f(){

// under the hood

var p = undefined;

console.log(p) // undefined

  if(true){
      p = true;
  }
}

f()

All makes sense, now let's take an example with functions this time!

function f(){

let num = 5;

  if(num < 10){
    function a(){
      console.log('less than 10')
    }

    a()
  } else if(num < 20){
    function a(){
      console.log('less than 20')
    }

        a()
  }  else {
    function a(){
      console.log('something else')
    }

    a()
  }
}

f()

This returns "less than 10" but why?

I expected the hoisting to happen like this:

function f(){
/* HOISTING 

 function a(){
      console.log('something else')
    }

// HOISTING COMPLETED
*/
let num = 5;

  if(num < 10){
 

    a()
  } else if(num < 20){
 
        a()
  }  else {
   

    a()
  }
}

f()

Since we had functions of the same name in each if-else block, a, the last one should have been used regardless of what value we put into our num variable!

We know if we have multiple functions of the same name, the last one is used since thats the one last hoisted as shown in this example:

function f(){

  b() // false

  function b(){
    console.log(true);
  }

  function b(){
    console.log(false);
  }
}

f()

So what's up with if-else?

This is the case with for-loop as well. For loops don't get their own execution context so variables declared using the var keyword and function declaration should also be hoisted to the top of their main function scope, shouldn't they? But this code wont work:

function f(){

  ff();

  for (let i=0; i<1; i++){

    function ff(){
      console.log(true);
    }
  }
}

f();

I expected the function inside for loop "ff" to be hoisted to the top of our main f function but it doesn't!

(Once again, I know it's a terrible practice to define two functions of the same name, or calling the function before its declaration, using the var keyword, etc. These are something you always wanna be avoiding but I'm diving deep and trying to clear questions like these)

imheretolearn1
  • 127
  • 1
  • 6
  • that's because hoisting happens during the parsing phase not the execution phase - therefore the last function wins – Jaromanda X Jul 01 '21 at 12:58
  • Yeah, don't use block-level functions because you get into all sorts of horrible edge cases. – VLAZ Jul 01 '21 at 12:59
  • [How does this hoisting work with block scope?](https://stackoverflow.com/q/66756997) | [confused about function declaration in { }](https://stackoverflow.com/q/58619924) | [What are the precise semantics of block-level functions in ES6?](https://stackoverflow.com/q/31419897) – VLAZ Jul 01 '21 at 13:02
  • 1
    Since 2015, ignoring web-compatibility mode, function declarations are block scoped, just like `let` and `const`. – Felix Kling Jul 01 '21 at 13:10

1 Answers1

-1

Variables seem to get hoisted in for loop hence why we get undefined at line 3!

f();

function f(){
console.log(v); // undefined

for (let i=0; i<1; i++){
  var v = true;
}

}

... but functions wont!

f();

function f(){

v(); **error: Uncaught ReferenceError: v is not defined**


for (let i=0; i<1; i++){
function v(){
console.log('hoisting wont happen')
}
}

}
imheretolearn1
  • 127
  • 1
  • 6
  • 1
    ES6 introduces block-level functions. So, they won't get hoisted out of their block scope, yes. With that said, web compatibility rules make then basically super annoying to use. – VLAZ Jul 01 '21 at 13:03