Check out a free preview of the full Deep JavaScript Foundations, v3 course

The "Hoisting" Lesson is part of the full, Deep JavaScript Foundations, v3 course featured in this preview video. Here's what you'd learn in this lesson:

Kyle debunks myths surrounding the concept of hoisting and clarifies what is actually happening under the hood.


Transcript from the "Hoisting" Lesson

>> Kyle Simpson: Let’s talk about hoisting. How many of you have heard the phrase hoisting before? Okay, it is thrown around or has been thrown around JavaScript for a long time. As well, variables hoist, and hoisting this and hoisting that. Until recently, that is within the last year or two, the word hoist literally did not even appear in the JavaScript specification.

Because it turns out that hoisting is not actually a real thing. The JavaScript engine does not hoist, it does not move things around the way it is suggested with hoisting. Hoisting is a metaphor that we have made up. It is a language convention that we have made up, and I mean English language convention.

It is an english language convention that we have made up to discuss the idea of lexical scope, without thinking about lexical scope, okay? And I'll show you why it doesn't actually exist, why it's really not even possible for it to exist with this very simple piece of code, it only takes a few lines.

If you try to explain what happens with line one, and we use the lexical scope discussion like we already talked about. Then you would first pass through this as the compiler, and then you would pass through it as an execution. But what people don't like doing, it seems, is thinking about this in terms of two passes.

People seem to be wanting to be stuck on passing through it just once. Two passes seems more confusing, just give me an explanation that works with a single pass. Whether it's true or not, I just want a more convenient explanation. And that's where hoisting comes from. Cuz hoisting says, well, we could explain what really happens here, if there was this magical behavior called hoisting.

Which was that any time JavaScript's execution engine entered a scope, it magically looked ahead and found all of the declarations wherever they were in that scope, and made variables for them, right? So it's as if the JavaScript engine goes and finds those variable declarations and moves them to the top of the scope before execution.

That's literally how hoisting is described. That's not what actually happens. JavaScript does not actually reorganize your code by moving the vars up to the top, and here is how I can prove to you that that's not what happens. Because, how would that magical look ahead actually work? How would it magically somehow when it enters the piece of code for the very first time on the very first pass, magically be able to at it and only find that declarations?

You certainly can't use regular expressions for that, because JavaScript is a non-regular language so regular expressions aren't good enough. So, how are you going to figure out where all the vars are? You're gonna do some very sophisticated processing on the tokens that come later in that block until you find the end of the block.

And then any of those places where a declaration could have occurred, then you can pull those out, and you could theoretically rearrange and move those. And guess what that magical, fancy processing would be called? Parsing, okay? That's called parsing. If you wanna find the variable declarations further down in the block, the only way you can do that is with parsing.

So hoisting isn't really a thing, it is a shorthand, a convention that we can use to try to describe something without needing to get into the nitty-gritty details. I'm not saying that it is a bad thing but what has been rather prevalent, as I have seen, in, I can't even count how many Stack Overflow.

When people asks questions about why JavaScript is doing something and it seems like it's weird or broken, and they post some code example. And then somebody says, well, it's because of the hoisting, and then this person says, Okay. And then it turns out that they're just wrong. This may be surprising to you, but did you know that stuff is wrong on Stack Overflow?

>> Speaker 1: [INAUDIBLE].
>> Kyle Simpson: Yes, shocking, I should have given you warning before dropping that knowledge bomb. This is a fact, there are posts on Stack Overflow where people have asked questions about my books, the You Don't Know JS books. And on one of those posts, many of them, but on one of these posts that I found, this person said, what does Kyle mean when, and he quoted some passage that I was talking about in my book.

I try as much as possible on Stack Overflow to go in and check for these, but there's too many and I have lost track of triaging questions on, that have been tagged with You Don't Know JS, or YDKJS. So, I ran across this post-one time, and so here's this question.

And I'm the one that wrote the book, my name is on the book. There is nobody on the planet that is more authoritative on the question of what did I mean than me.
>> Speaker 2: [LAUGH]
>> Kyle Simpson: Can we agree with that?
>> Speaker 2: Good point, there.
>> Kyle Simpson: Okay? Whether I'm wrong about JavaScript is a separate issue, but what I mean, I'm the authoritative on the spec, okay?

>> Speaker 2: [LAUGH]
>> Kyle Simpson: Somebody else answered the question, and they were completely wrong. Just 100% totally wrong. I don't feel, I'm not like down on that person, people make mistakes, they don't understand stuff. But here's what was so demoralizing, the green check mark and over 4000 uploads. Even when I post my little answer there is now like 17 uploads, it's never going to get seen by anybody.

So you can't always trust what you read on Soccer List. Sorry for that little digression, okay?
>> Speaker 3: We can help you. We can all upvote you.
>> Kyle Simpson: Yeah, we can get 100 more votes [LAUGH]. It's not gonna get me to 4000. But anyway, so, the point that I was making is there's lots of questions where people will ask questions about this whole hoisting thing, and they'll say I'm frustrated because this doesn't seem to work the right way or what am I.

And somebody will answer it and they'll use hoisting, and it will perpetuate inaccuracy. It is not that hoisting is unhelpful to you, but when you use hoisting, and you don't know the nuances, and you don't know what's actually happening, then you actually get misled into thinking the wrong thing.

Which is why I first taught you ow it really works, and how we're circling back to the more shorthand definition, because armed with both of those, you can make sure in the future that you don't get confused. But armed only with hoisting, it only takes a few lines of code for me to confuse a developer.

So it is not the case that these get moved up, just like it is not the case that functions get reassigned. This code, if we were trying to figure out what it did, we would say according to hoisting, that this is what it did. It moved the function first, and then it moved the variable declaration, and then it executed.

For the exact same reason it doesn't lose variables, it doesn't lose functions. It handle them during the first pass, and then it execute. There is, however, and important distinction to be made here on this slide, which is the difference between a function declaration and a function expression. A number of you were asking when we were talking about error functions, hey well, isn't it okay if I just assign my favorite loving error function to a variable?

Is it okay? Yes. Will it work? It depends. In this particular example, we have the functions having to move to the top, but notice what happened to the function assignment on line 9, it's still only happens on line 9. Which means that line seven is going to throw a type error.

So in other words, to use the form of function where you only assign it to properties or variables, you have to have all of your functions defined before you call them. Some people like that. As a matter of fact, for probably more than 15 years of my development career, I did exactly that.

Probably because I have roots in programming languages like C. I got used to the habit of having all my functions at the top, and all my executable code at the bottom. And one day, about five, six years ago, maybe almost seven years ago at this point, it just dawned on my one day, why am I putting all my functions at the top, and then every time I open up this file, I've gotta scroll 3,000 lines before I can find my executable code?

Why can't I just put that code at the top, so it's right there when I open up the file? And it's real obvious what the code does. If I need to look at the functions, they're still there, but I wanna find the executable code easily. And finding it at the bottom is a lot of harder than finding it at the top.

And so I just started putting all the functions at the bottom of any scope. And not only do I do that in the top scope, but I also do that within scopes. I put the executable code at the top, and I put my function declarations at the bottom.

And I take advantage of the fact that functions hoist. They hoist, right? They are taken at compile time and defined in such a way so that they can be used even earlier in the scope than when they've been declared. So there are many, many people that say that JavaScript's hoisting mechanism is a bad, poorly designed, buggy part of the system.

And it's why JavaScript doesn't qualify as a lexically scoped language because of hoisting, and we shouldn't use it, and shouldn't rely upon it. And as with most things, it kinda depends, it depend on your perspective of what you're trying to accomplish. It is sometimes the case that hoisting is bad, and sometimes the case I think it's quite useful.

Learn Straight from the Experts Who Shape the Modern Web

  • In-depth Courses
  • Industry Leading Experts
  • Learning Paths
  • Live Interactive Workshops
Get Unlimited Access Now