Prerequisites
- Understand what an execution context is and its phases.
- Understand how to determine the scope of a variable in JavaScript.
Hoisting
Hoisting is the process by which JavaScript allocates memory for variable and function declarations.
When Does Hoisting Occur
Hoisting occurs before code execution during the creation phase of an execution context. Recall that the JavaScript engine allocates a variable environment to store local variables during the creation phase of an execution context. When we access a variable or function in our program, we access a property on the variable environment.
The JavaScript engine, during hoisting, scans the code for variable and function declarations, and with each declaration, the JavaScript engine adds a property to the variable environment. The initial value associated with each property depends on how the variable or function was declared.
Hoisting Rules
Type | Initial Value | What it means |
Function Declaration | Actual Function | You can access and call a function before its declaration |
var | undefined | You can access a variable declared with var before its declaration, but it will have an undefined value. Because the variable exists in the scope, it will not result in an error. |
let and const | uninitialized | You can't access a variable declared with let and const before its declaration. Variables declared with let and const don't exist in the scope until you declare them. Thus you will get an error when you try to access the variable. |
Function expressions and arrows | It depends on whether the function expression or arrows uses var, let, or const | It will follow the rules of the keyword used to define the function |
Visualizing Hoisting
Stop and think
What will the call to the function greet() in the code below output?
function greet() {
console.log('Hello');
}
greet();
function greet() {
console.log('Jambo');
}
Answer
Answer: Jambo
Remember, the JavaScript engine hoists function declarations before code execution, with the initial value being the function. We have a function called greet
declared twice; therefore, the JavaScript engine will hoist the greet
function declared last.
Recall also that when we access a variable, we are accessing the properties on the variable environment. The variable environment doesn't change for function declarations when code execution begins. Therefore, when we call greet
anywhere in our program, the value hoisted will be used, and in our case, it is the greet function declared last.
Temporal Dead Zone (TDZ)
Recall from the hoisting rules that variables declared with let and const don't exist until we declare them.
TDZ is a fancy term for the region within a scope for which a variable is declared but can't be accessed. The TDZ starts at the beginning of the scope till when the variable is defined.
In the code example above, the TDZ of the variable square
is the region highlighted in purple. Trying to access the variable square
in that region will result in an error.
Test Your Understanding
1. What is the output?
if (!s) {
console.log(t);
var t = 8;
console.log(t);
}
var s = 10;
if (s === 10) {
console.log(t);
}
Answer
undefined
8
8
The variable s
is hoisted with the initial value being undefined. The first if block, therefore, accesses a variable before its declaration and shows the dangers of declaring variables with the var
keyword. With ES6, stick to declaring variables with let and const.
2. What is the output?
var favoriteCar = 'Lamborghini';
function foo() {
console.log(favoriteCar);
var favoriteCar = 'Porsche';
console.log(favoriteCar);
}
foo();
console.log(favoriteCar);
Answer
undefined
Porsche
Lamborghini
Variables declared with var
have function scope. When we call the function foo
, we create a new execution context, and thus the variable favoriteCar
gets hoisted in this new execution context's variable environment.
3. What is the output?
function greet() {
function a() {
console.log('Ola');
}
return a();
function a() {
console.log('Hello');
}
}
greet();
Answer
Hello
Remember, function declarations get hoisted before code execution, with the actual function as the initial value. While statements after the return
keyword are unreachable during execution, the function was already hoisted.
4. What is the output?
const radius = 15;
function computeCircumference(radius) {
return 2 * PI * radius;
}
const PI = 3.14;
const square = computeCircumference(radius);
console.log(square);
Answer
94.2
5. What is the output?
var y = 7;
if (true) {
var y = 10;
console.log(y);
}
console.log(y);
Answer
10
10
Variables declared with var can be redclared.