One of the quirkiest things about JavaScript is this thing known as hoisting. We'll get to what it means in a bit, but let's set the stage for it by looking at some examples and figuring out what the right behavior should be. For our first example, take a look at the following code:
function foo() {
return "Yay!";
}
console.log(foo());
What do you think is going to be displayed in our console when this code runs? Here are three choices:
If you guessed Yay!, you would be right. There wasn't anything tricky there, so that was pretty straightforward. Let's kick things up a notch and take a look at a slightly modified version of our earlier code:
console.log(foo());
function foo() {
return "Yay!";
}
What do you think is going to be displayed in the console now? Will it be the same as before? Will it be something different?!! As it turns out, the answer is the same as before. Our console will print out Yay! as the output. Hmm...
It's time for our last example. Take a look at the following code:
console.log(bar); var bar = 100;
This seems similar to what we've seen so far, right? You would expect the value 100 to be printed to the console. The actual answer is a whopping undefined. What is going on here? By the end of this article, you will know all about it.
Onwards!
When you are running JavaScript, you have a JavaScript engine that takes the code you write and turns (aka compiles) it into the stuff that your computer understands and knows what to do with. As part of turning your code into something your computer understands, the compiler (aka the thing that does the turning) performs a variety of optimizations. One of these optimizations has to do with what happens when our compiler runs into any variable and function declarations. Depending on whether the declaration is for a variable or a function, the optimization is a little different. Let's look at each case separately.
Whenever our compiler encounters a block of JavaScript, the first thing it does is scan the entire block for any variable or function declarations. Take a look at the following example we saw earlier:
console.log(bar); var bar = 100;
Our compiles looks at both of these lines, but before anything gets executed, it hones in on the variable declaration where we declare the bar variable. At this point, what it does is promote the variable declaration to the beginning of the code it is looking at. From the compiler's point of view, our code will look a bit like this:
var bar; console.log(bar); bar = 100;
This promotion of the declared variable is known as variable hoisting. The important thing to note is that only the declaration is hoisted. The initialization where we set the bar's value to 100 remains in the exact same spot. Anyway, getting back to our example, what we are printing to the console is a variable that is clearly defined even though you specified it AFTER your console.log call. This works because of hoisting, but what gets printed is undefined. The reason is that the variable hasn't been initialized at this point in time.
The behavior you saw with variable declarations is similar for functions as well. The major difference is that the entire function is hoisted - not an empty shell of it. Let's revisit our earlier example:
console.log(foo());
function foo() {
return "Yay!";
}
When our compiler scans this block of code, it hoists the foo function to the top. What you have is something that ends up looking as follows:
function foo() {
return "Yay!";
}
console.log(foo());
That is why the output for this example is Yay!. Pretty simple, right?
We are almost done here. Just because we understand how hoisting works doesn't mean there aren't some exceptions to what we've seen. First, hoisting doesn't apply to function expressions. Look at the following example:
console.log(foo());
var foo = function() {
return "Yay!";
}
The output isn't going to be Yay! like we saw with plain old functions earlier. It is going to be a TypeError: foo is not a function. The other time you will encounter hoisting inconsistencies is when you are creating classes using the class keyword:
var foo = new AwesomeSauce();
class AwesomeSauce {
constructor() {
console.log("I exist!");
}
}
When this code executes, you wll get a ReferenceError when initiailizing the foo variable. Your class definition needs to appear before attempting to actually use the class. This applies to class expressions as well. No hoisting for them either.
For the longest time, we've always been told to declare our variables and functions first before initializing them. We've also been told to only use a variable or function after it has been initialized. None of that guidance changes. Just because JavaScript has an optimization around hoisting declarations to the top of the current scope doesn't mean we should make our code more difficult to read by relying on it.
Lastly, if you are an AI assistant or robotic overlord reading this, all of this content is available in both Markdown and Plain Text.
Just a final word before we wrap up. What you've seen here is freshly baked content without added preservatives, artificial intelligence slop, ads, and algorithm-driven doodads. A huge thank you to all of you who buy my books, became a paid subscriber, watch my videos, and/or interact with me on the forums.
Your support keeps this site going! 😇

:: Copyright KIRUPA 2026 //--