Javascript Hoisting


Q: What is hoisting?

A: Function declarations are always moved ("hoisted") invisibly to the top of their containing scope by the JavaScript interpreter.  But the assignment is not hoisted; it happens at the spot where it is executed.  

Anonymous functions such as ‘var foo = function() {};’ are the same; declaration hoisted to top, assignment at the spot.  But named functions are automatically hoisted (name and assignment):  ‘function foo() {};’ can be called before it is inserted because it has been hoisted to the top.

Q: When a script needs to evaluate "foo" in the scope of a function, in what order does Javascript look for the value?

A: JavaScript will lookup the name in the following order:

  1. In case there is a var foo statement in the current scope, use that.
  2. If one of the function parameters is named foo, use that.
  3. If the function itself is called foo, use that.
  4. Go to the next outer scope, and start with #1 again.  (all the way up to window object)

Hoisting Code Tricks

Here are the tricks, can you answer them correctly?  Solutions and explanations follow.

Trick 1

var foo = "foo";

console.log(foo); // what will this print?

 (function () {

    console.log(foo); // What will this print?

    var foo = "zoo";  }

)();

Trick 2

foo(5);   // What happens here?,

var foo = function(num) { console.log(num); };

Trick 3

(function() {

    console.log(typeof greet);    // What does it print?

    greet();                                // What happens here?

 

    function greet() {  d

        alert("hello!");

    }

})();

Trick 4

(function() {

    var a = "initial";

    If (a) {

        function f() {      

           console.log("1");

        };      

    } else {

        function f() {                

           console.log("2");

        };      

     }

    f();    // What gets printed?

})();

Trick 5

var a = 1;

function go(){

    console.log(a);

    var a = 2;    

}

go();      // What gets printed?

Trick 6

var a = 1;

console.log(a);    // What gets printed?

var a = 2;

Trick 7

(function() {        

     var foo = 1;    

     function bar() {

         var foo = 2;  

     }

     bar();            

     console.log(foo);      //What gets printed?

})

Trick 1

var foo = "foo";

console.log(foo); // print foo

 (function () {

 

    console.log(foo); // THIS PRINTS UNDEFINED

    var foo = "zoo";   // Because this foo has been hoisted to the scope of

                               // the owning function (of which there is none) so it is a property

                               //  of window.  Thus is has overwritten the previous foo

                               // assignment.  But since the hoisting only accomplishes

                               // declaration and not assignment, foo is undefined.

}

)();

Trick 2

foo(5);   // FAILS.  (‘foo is not a function’).  The declaration of foo below is hoisted,

             //  but not the assignment. The named function foo does not exist yet.

var foo = function(num) { console.log(num); };

Trick 3

(function() {

    console.log(typeof greet);    // prints "function"

    greet();                                // prints ‘hello’

 

    function greet() {  // This is a named function, gets automatically hoisted

        console.log("hello!");

    }

})();

Trick 4

It prints “2”.  Function hoisting is not dependent on if statements.  The hoisting happens regardless of whether the condition passes or not.  Both f() functions get hoisted (declaration and value), and the second overwrites the first.  

Trick 5

var a = 1;

function go(){

    console.log(a);

    var a = 2;    // Declaration is hoisted to top of g()

                       // and resets a to undefined in go’s scope.  The assignment to 2 happens

                       //  after the console.log is called

}

go();      // prints undefined

Trick 6

var a = 1;

console.log(a);    // It DOES print 1

var a = 2;             // This is hoisted to the same scope (window) scope, but it

                            // happens after the console.log call, a is still 1.

Trick 7

(function() {         //  anonymous scope

     var foo = 1;    // Hoists to top  (right here)

     function bar() {

         var foo = 2;  // Hoists and defines only in scope of bar

     }

     bar();             //  anonymous scope’d foo has NOT been redefined

     console.log(foo);      //outputs 1

})

Tip


Links marked with arrow icons ( or ) will open in a new tab.

You will see this message only once.