Hoisting in JavaScript

Share this article

Key Takeaways

  • Hoisting in JavaScript refers to the interpreter’s action of moving all variable and function declarations to the top of the current scope, allowing you to use variables and functions before they are declared in the code. However, only the declarations are hoisted, not the assignments.
  • Function declarations are hoisted in JavaScript, allowing the function to be called before it is declared in the code. However, function expressions, including those involving arrow functions, are not hoisted, leading to an error if called before their definition.
  • Variables declared with ‘var’, ‘let’, and ‘const’ are all hoisted in JavaScript, but they behave differently. ‘Var’ is initialized with ‘undefined’ when hoisted, allowing its use before declaration. ‘Let’ and ‘const’, while hoisted, are not initialized, resulting in a Reference Error if accessed before declaration. This period is known as the Temporal Dead Zone.
Variable declarations are one of the most basic aspects of any programming language. However, JavaScript has a little quirk, known as hoisting, which can turn an innocent looking declaration into a subtle bug. This article explains what hoisting is, and how you can avoid being burned by it. Simply, hoisting in JavaScript allows you to use variables and functions before they are declared in the code, because the JavaScript interpreter automatically moves the declarations to the top of their scope before the code is executed. JavaScript is an extremely flexible language, and will happily allow you to declare a variable almost anywhere. For example, the following immediately-invoked function expression (IIFE) declares three variables and then displays them using an alert dialog box. As a side note, you should never use alert boxes, but we’re trying to prove a point here.
(function() {
var foo = 1;
var bar = 2;
var baz = 3;

alert(foo + " " + bar + " " + baz);
})();
This looks like sane JavaScript code. As expected, it displays the string "1 2 3". Now, assume that the alert is moved, as shown below.
(function() {
var foo = 1;
alert(foo + " " + bar + " " + baz);
var bar = 2;
var baz = 3;
})();
If someone actually wrote this code, it was probably by mistake. Clearly, the alert takes place before bar and baz are declared. However, this is perfectly valid JavaScript, which does not generate an exception. Instead, the alert displays "1 undefined undefined"
. Based on our previous experiment, it seems that you can reference variables that don’t exist yet. Now, let’s take the same IIFE, but remove the baz declaration altogether, as shown below. Suddenly, we have a ReferenceError because baz is not defined.
(function() {
var foo = 1;
alert(foo + " " + bar + " " + baz);
var bar = 2;
})();
This is truly interesting behavior. To understand what’s going on here, you have to understand hoisting. Hoisting is the JavaScript interpreter’s action of moving all variable and function declarations to the top of the current scope. However, only the actual declarations are hoisted. Any assignments are left where they are. Therefore, our second example IIFE actually translates to the following code.
(function() {
var foo;
var bar;
var baz;

foo = 1;
alert(foo + " " + bar + " " + baz);
bar = 2;
baz = 3;
})();
Now it makes sense why the second example didn’t generate an exception. After hoisting, bar and baz are actually declared before the alert statement, albeit with undefined values. In the third example, baz was removed completely. Therefore, there was nothing to hoist, and the alert statement resulted in an exception.

Function Hoisting

As previously mentioned, function declarations are also hoisted. However, functions that are assigned to variables are not hoisted. For example, the following code will work as expected due to function declaration hoisting.
foo();

function foo() {
alert("Hello!");
}
However, the following example will fail spectacularly. The variable declaration for foo is hoisted before the function call. However, since the assignment to foo is not hoisted, an exception is thrown for trying to call a non-function variable.
foo();

var foo = function() {
alert("Hello!");
};

Conclusion

Hoisting is an easy to understand, but often overlooked nuance of the JavaScript language. Without a proper understanding of hoisting, your programs are susceptible to subtle bugs. To help avoid these bugs, many developers (and linting tools) advocate for a single variable declaration statement at the very beginning of every scope. Since this is how the JavaScript interpreter essentially sees your code, there is validity to this rule – even if I am personally guilty of breaking it.

Frequently Asked Questions about JavaScript Hoisting

What is the difference between var, let, and const in terms of hoisting in JavaScript?

In JavaScript, all three, var, let, and const, are hoisted. However, they behave differently. When ‘var’ is hoisted, it is initialized with ‘undefined’. This means you can use a variable declared with ‘var’ before its declaration. On the other hand, ‘let’ and ‘const’ are also hoisted but are not initialized. Therefore, if you try to use a ‘let’ or ‘const’ variable before its declaration, you will get a Reference Error. This area between the start of the scope until the declaration is known as the Temporal Dead Zone.

Can functions be hoisted in JavaScript?

Yes, functions can be hoisted in JavaScript. Function declarations are hoisted completely to the top of their scope. This means that the function can be called before it is declared in the code. However, function expressions, including those involving arrow functions, are not hoisted. If you try to call a function expression before its definition, you will get an error.

What is the Temporal Dead Zone in JavaScript hoisting?

The Temporal Dead Zone (TDZ) is a behavior in JavaScript related to ‘let’ and ‘const’ variables. It’s the period from the start of the scope until the declaration is processed, during which these variables cannot be accessed. If you try to access them, JavaScript will throw a Reference Error. The TDZ ends after the line of code where the variable is declared.

How does hoisting affect the order of code execution in JavaScript?

Hoisting can significantly impact the order of code execution in JavaScript. Since variable and function declarations are moved to the top of their containing scope during the compile phase, it allows you to use functions and variables before they are declared in the code. However, it’s important to note that only the declarations are hoisted, not the initializations.

Is it possible to avoid hoisting in JavaScript?

Hoisting is a default behavior in JavaScript and cannot be turned off. However, you can manage it effectively by always declaring variables and functions at the top of your scope. This way, you can ensure that hoisting does not lead to unexpected results in your code.

How does hoisting work with classes in JavaScript?

Class declarations, like function declarations, are hoisted. However, they are not initialized with ‘undefined’. Therefore, if you try to instantiate a class before its declaration, JavaScript will throw a Reference Error. This is similar to the behavior of ‘let’ and ‘const’ variables.

How does hoisting work in ES6 and later versions?

In ES6 and later versions, ‘let’ and ‘const’ were introduced, which have different hoisting behavior compared to ‘var’. While ‘var’ variables are hoisted and automatically initialized as ‘undefined’, ‘let’ and ‘const’ variables are hoisted but remain uninitialized. This means that a Reference Error will be thrown if they are accessed before their declaration.

What is the impact of hoisting on JavaScript performance?

Hoisting does not have a significant impact on JavaScript performance. The JavaScript engine processes the hoisting during the compile phase, not the execution phase. Therefore, it does not affect the runtime performance of the JavaScript code.

Can hoisting lead to bugs or errors in JavaScript code?

Yes, hoisting can potentially lead to bugs or errors in your JavaScript code. This is especially true if you try to use a variable before it’s declared and initialized. To avoid such issues, it’s a good practice to always declare and initialize your variables at the top of their scope.

How does hoisting work with JavaScript modules?

In JavaScript modules, ‘var’, ‘let’, ‘const’, and function declarations are hoisted to the top of the module, not to the global scope. This is because each module in JavaScript has its own scope. However, they follow the same hoisting rules as in the global or function scope.

Colin IhrigColin Ihrig
View Author

Colin Ihrig is a software engineer working primarily with Node.js. Colin is the author of Pro Node.js for Developers, and co-author of Full Stack JavaScript Development with MEAN. Colin is a member of the Node.js Technical Steering Committee, and a hapi core team member. Colin received his Bachelor of Science in Engineering, and Master of Science in Computer Engineering from the University of Pittsburgh in 2005 and 2008, respectively.

functionsHoisting
Share this article
Read Next
Get the freshest news and resources for developers, designers and digital creators in your inbox each week