Quick Tip: JavaScript Hoisting Explained
basixvideos

Quick Tip: JavaScript Hoisting Explained

Tutorial Details
  • Topic: JavaScript
  • Difficulty: Basix
  • Format: 5 Minute Screencast
Download Source Files

Today’s video quick tip comes in response to a question on Twitter, concerning JavaScript “hoisting.” What is it? How does it work? What do you need to know about it? All of that will be covered in this beginner-focused fundamentals lesson.


Hoisting Explained

Consider the following code:

var myvar = 'my value';
alert(myvar); // my value

Okay, of course the alert will display “my value.” That’s obvious; however, stick with me. Let’s next create an immediate function, which alerts the same value.

var myvar = 'my value';

(function() {
  alert(myvar); // my value
})();

All right, all right. Still obvious, I know. Now, let’s throw a wrench into the mix, and create a local variable within this anonymous function of the same name.

  var myvar = 'my value';

(function() {
  alert(myvar); // undefined
  var myvar = 'local value';
})();

Huh? Why is the alert now displaying undefined? Even though we’ve declared a new variable, it’s still below the alert; so it shouldn’t have an effect, right? Wrong.


Variable Declarations are Hoisted

Within its current scope, regardless of where a variable is declared, it will be, behind the scenes, hoisted to the top. However, only the declaration will be hoisted. If the variable is also initialized, the current value, at the top of the scope, will initially be set to undefined.

Okay, let’s decipher the difference between the terms, declaration and initialization. Assume the following line: var joe = 'plumber';

Declaration
var joe; // the declaration
Initialization
joe = 'plumber'; // the initialization

Now that we understand the terminology, we can more easily comprehend what’s happening under the hood. Consider the following bogus function.

(function() {
  var a = 'a';
  // lines of code
  var b = 'b';
  // more lines of code
  var c= 'c'; // antipattern
  // final lines of scripting
})();

Declare all variables at the top.

Note that what’s exemplified above is considered to be bad practice. Nonetheless, behind the scenes, all of those variable declarations — regardless of where they occur in the function scope — will be hoisted to the top, like so:

(function() {
  var a, b, c; // variables declared
  a = 'a';
  // lines of code
  b = 'b'; // initialized
  // more lines of code
  c= 'c'; // initialized
  // final lines of scripting
})();

Aha Moment

If we now return to the original confusing undefined piece of code, from above:

 var myvar = 'my value';

(function() {
  alert(myvar); // undefined
  var myvar = 'local value';
})();

It should now make perfect sense why myvar is alerting undefined. As we learned, as soon as the local variable, myvar, was declared, it was automatically hoisted to the top of the function scope…above the alert. As a result, the variable had already been declared at the time of the alert; however, because initializations aren’t hoisted as well, the value of the variable is: undefined.

Add Comment

Discussion 31 Comments

  1. First! Nice tutorial :)

    Didn’t know about this.

  2. Juan says:

    Need some minutes to digest it, thanks :)!

  3. Nico says:

    I remember hearing about something like this, but this article refreshed my memory. :) It’s an interesting way for a language to work. But then again a smart way to force practice.

  4. JavaScript makes me sick again. ;] Still thanks for this tip!

  5. Eduardo Barros says:

    Great tutorial, jeffrey.

    BTW, I see you haven’t used any editor other then VIM for your screencasts, really liking it, uh? Are you 30 days over?

  6. Nice quicktip. One question about this, though it probably varies from engine to engine I would guess. When the engine goes to get all the vars and “hoist” them to the top of the function, does it run some type of check to see if it is already at the top? Otherwise I don’t see how it is an advantage to put the vars at the top of the function rather than throughout the code performance wise. I prefer it at the top anyways as it is more clean to me, but just curious about how the hoisting actually checks for location or if it hoists all vars no matter the location.

    • Scriptin says:

      Var/function hoisting is a part of ECMAScript standard, even it’s last (5th) edition, but it has changed a bit, as I can understand. The rules of scoping is complicated, so the behavior, I think, can vary in the cases when engines implement different versions of standard.

      So, I wouldn’t rely on engine and rather try to handle naming/scoping myself.

      There is a gotcha when using ‘return’ befova var declaration: http://stackoverflow.com/questions/3725546/variable-hoisting

  7. Julian says:

    Nettuts ate my comment for some strange reason…

  8. Regis says:

    Nice! It’s those little dark corners that can hurt the most. Thank you for shedding light!

  9. kim edgard says:

    I use it always…Its an anonymous functions…the (); means execute…

  10. fritz says:

    I always declare all my vars at the start of my functions exactly to avoid that problem.

  11. Oh my god!
    I never knew that!

    Nice tip..

  12. Ryan says:

    Awesome! I learned something today. Great article.

  13. Alex Bars says:

    Seriously,if one doesn’t know about it, have a HUGE path to dig into!!

  14. Jeremy says:

    Actually, if I paste your exact code in to Firebug, it alerts “my value”. So, in Firefox 3.6 at least, this article is complete garbage.

    • Jeremy says:

      Ok, complete garbage is a little harsh, but my point is, if you’re going to write an entire article about “Javascript” behavior, and you don’t even test it in the second largest browser on the market (did you base this article on IE? Chrome? Safari?), you’re at best not doing obvious/basic research, and at worst spreading mis-information.

      • Jeffrey Way says:
        Author

        You’re right, garbage is a little harsh, particularly when you’re wrong. :)

        I, again, just tested this code in Firebug, and it alerted “undefined,” as expected.

        Is this the code you tested?

         var myvar = 'my value';
        
        (function() {
          alert(myvar); // undefined
          var myvar = 'local value';
        })();
        
      • HeObiouslyPasteItWrong says:

        he obviously paste it wrong

  15. This is very useful to know.
    I have never come across this issue and was also unaware of it.
    Thanks.

  16. Alex Bars says:

    I advice one try to study this little details through books, and ECMAScript Specification!!

  17. Kent says:

    Huh, I sure didn’t know about this.

  18. evan-xg says:

    I think this is the work around on the constraint found in c language which require to declare at the top

  19. Jonathan says:

    Very interesting, thanks Jeffery.

    Never personally encountered a problem due to this, maybe it’s my personal coding style (or more likely, luck).

    I love these articles about how underlying things work – more please.

  20. Etnas says:

    Very interesting;
    I have wrote a small article about this topic on my web site. It’s on spanish, so It could be a great complement to this:

    http://www.etnassoft.com/2010/12/26/hoisting-en-javascript/

    Good work, guys!

  21. Fawad Hassan says:

    Very nice tip Jeff :)
    Thanks for sharing

  22. RSturim says:

    Thanks Jeffrey, this is the best demonstration on ‘hoisting’ I’ve seen — it definitely clears things up … the detail on how function expressions are also hoisted offered an important ‘aha’ moment for me.

  23. Rob says:

    You go REALLY FAST in the video. I wish you would slow down and explain things a little better for us noobs! I am going to try reading the text under it and hope that is a better format to learn from.

  24. Jaime says:

    Well explained.

Add a Comment

To add a code snippet to your comment, please wrap your code like so: <pre name="code" class="html">YOUR CODE</pre>. You can replace the class name with "js," "css," "sql," or "php." If there are any "<" or ">" within your code, please search and replace them with: &lt; and &gt; respectively.