Search code examples
javascripthoisting

unexpected results with function and variable hoisting


I'm reading the second book of the series "You don't know JS" and I've read that functions are hoisted before variables.

So this is the code:

foo(); // 1

var foo;

function foo() {
    console.log( 1 );
}

foo = function() {
    console.log( 2 );
};

The output of this will be 1. But why? Functions are hoisted first and then variables. So after my function foo (the one that prints 1) is hoisted it has to be followed by the variable foo. So the result should be "undefined" instead of "1".

I expect the code to behave as if it had been:

// hoisted first
function foo() {
    console.log( 1 );
}

// hoisted second
var foo;  // implicitly initialized to 'undefined'

foo();  // call 'undefined' - error?

foo = function() {
    console.log( 2 );
};

What's happening here?


Solution

  • As said, functions are hoisted before variables; if the interpterer comes across var foo after foo has already been defined in the scope, it will simply be ignored. It doesn't assign foo to undefined, it only ensures that a variable named foo exists in the current scope - which it already does.

    As it says in your You Don't Know JS link:

    multiple/duplicate var declarations are effectively ignored

    Here's another commonly seen example of hoisted duplicate variables being ignored that might be more familiar/intuitive:

    if (false)
      var foo = false;
    else
      var foo = true;
    

    turns into

    var foo;
    var foo; // does not actually do anything; does not assign `undefined` to `foo`, ignored
    // foo just *happens* to not have anything assigned to it in almost all cases like this
    if (false)
      foo = false;
    else
      foo = true;