It's always a good time to review the basics of your programming language! In this series I'll be reviewing some fundamentals of JavaScript. It is important that we refresh ourselves on how the language works behind the scenes and of course it is also great practice to be able to explain concepts in simple terms.
This week we review Hoisting - what it is, function and variable hoisting, and a few key takeaways.
What is Hoisting?
When your JavaScript code is compiled, variable and function declarations are "hoisted" to the top of their scope. Depending on where a variable is declared, the scope could be global or local. Either way, the variable declaration is hoisted to the top of that specific scope. Functions are also hoisted, but to the very top of the program. Functions are hoisted even above global variables. Hoisting is why you might see functions successfully called before they are declared - to make this possible they are pulled (hoisted) to the top of your program right before the code is executed.
It is important to note that when code is hoisted it is not physically relocated in your program. Instead, your program is scanned for all variable/function declarations and those relationships are saved in the lexical environment. Your code maintains its original formatting and structure while variable/function declarations are accessible via lexical environment.
Hoisting Functions:
- Function Declarations are hoisted to the very top of the program. They can be called in the code prior to actual declaration. The example below logs without error:
-
Function Expressions are not completely hoisted in the program. Instead, only the declaration will be hoisted because it is recognized as a variable (hint:
var
keyword). The actual assignment of the variable's value (in this case a function) is not hoisted. In the example below, you'll first get an error stating that expression is not a function. That is because the assignment was not hoisted - only the declaration. The second call ofexpression()
works, because the program has parsed through the program ad reached the assignment of the function tovar expression
.
Hoisting Variables:
Variables are hoisted to the top of their scope (local or global). Variables declared with var
are hoisted slightly differently that variables declared with const
or let
.
-
var Variables are hoisted, initialized, but assigned value of
undefined
. Similar to function expressions only the declaration is hoisted, not the actual assignment of the variable's value. The code below demonstrates howvar
variables are hoisted, initialized with a value ofundefined
, and then reassigned their value once the program reaches the value assignment.
-
let/const Variables are a little more tricky. These variables are hoisted, but remain uninitialized until they are evaluated. Unlike the
var
variables which are hoisted and initialized with a value ofundefined
,let
/const
variables are hoisted, but not initialized at all. That means they're sitting in the lexical environment uninitialized. Attempting to access a variable that is uninitialized throws a reference error. Once the program is in execution and reaches the variable declaration, yourlet
/const
variable will be initialized. It will either be initialized with a value (if assigned in the declaration line) or withundefined
until a value assignment is reached later on in the code.
This can be rather confusing at first, so let's take a look at the example below. You'll see that first an error is thrown because while the variable exists in the lexical environment, it remains uninitialized until the program reaches the line of variable declaration. Line 11 the variable gets initialized, but is assigned a value of undefined
because there is no value assignment. Line 13 the variable is assigned a value which overwrites previous value of undefined
.
Take a look at the example below which showcases let
/var
variables and their hoisting differences side by side:
Key Takeaways!
- Variable declarations are hoisted, while variable definitions are not.
- Function declarations are hoisted, while function expressions are not.
- Variables with
var
are hoisted, initialized, and assigned value ofundefined
- Variables with
let
/const
are hoisted, but remain uninitialized until their variable declaration code is reached. Then, they are either assignedundefined
or a value depending if value assignment exists. - It is helpful to declare your variables at the top of the function scope. This way, it is clear where variables are coming from and easier to identify their scope.
- Declare and initialize your variables before use to avoid bugs which stem from incorrect hoisting assumptions.
Top comments (3)
Nice article!
Just got confused with the var/let prints, had to test it to check how it works prefectly.
It would be nicer if the prints had the same lines, just changing var to let.
Aside of that, this helped me understand some things!
Thanks for sharing!
Great feedback, Victor! I think I'll add an additional image showing the same lines with var/let.
Got the clarity about the function declaration and the function expression . Nice Article