Search code examples
javascripthoisting

Hoisting of javascript with block statement


foo(); 

var a = true;
if (a) {
   function foo() { console.log( "a" ); }
}
else {
   function foo() { console.log( "b" ); }
}

My expected output is b but when I try to run in browser got foo is not a function


Solution

  • The similar piece of code is explained in MDN Conditionally created functions

    Functions can be conditionally declared, that is, a function statement can be nested within an if statement, however the results are inconsistent across implementations and therefore this pattern should not be used in production code. For conditional function creation, use function expressions instead.

    var hoisted = "foo" in this;
    console.log(`'foo' name ${hoisted ? "is" : "is not"} hoisted. typeof foo is ${typeof foo}`);
    if (false) {
      function foo(){ return 1; }
    }
    
    // In Chrome:
    // 'foo' name is hoisted. typeof foo is undefined
    //
    // In Firefox:
    // 'foo' name is hoisted. typeof foo is undefined
    //
    // In Edge:
    // 'foo' name is not hoisted. typeof foo is undefined
    //
    // In Safari:
    // 'foo' name is hoisted. typeof foo is function
    

    The results are exactly the same for a condition that evaluates to true.

    var hoisted = "foo" in this;
    console.log(`'foo' name ${hoisted ? "is" : "is not"} hoisted. typeof foo is ${typeof foo}`);
    if (true) {
      function foo(){ return 1; }
    }
    
    // In Chrome:
    // 'foo' name is hoisted. typeof foo is undefined
    //
    // In Firefox:
    // 'foo' name is hoisted. typeof foo is undefined
    //
    // In Edge:
    // 'foo' name is not hoisted. typeof foo is undefined
    //
    // In Safari:
    // 'foo' name is hoisted. typeof foo is function
    

    It looks like you took the piece of code from You-Dont-Know-JS book series where author tried to give an explanation about this too:

    Function declarations that appear inside of normal blocks typically hoist to the enclosing scope, rather than being conditional as this code implies: ...

    [...code...]

    However, it's important to note that this behavior is not reliable and is subject to change in future versions of JavaScript, so it's probably best to avoid declaring functions in blocks.