JavaScript hoisting is one of the most important yet often misunderstood concepts for developers, especially when working with variable declarations and function scopes. Hoisting essentially allows you to use functions and variables in your code even before they are formally declared. While this might seem like magic, understanding how JavaScript interprets and rearranges code can help you avoid common pitfalls and write more predictable, efficient programs.
In this article, we’ll dive into hoisting through a series of output-based questions, ranging from beginner to advanced levels. Each question is followed by an explanation of the concept behind it, helping you solidify your understanding of how JavaScript hoists variables and functions during execution.
Let’s explore some key hoisting-related output questions and break down the behavior you need to be aware of when writing JavaScript.
1. Variable Hoisting with var
Question:
console.log(x);
var x = 10;
console.log(x);
Output:
undefined
10
Explanation:
In JavaScript, var declarations are hoisted to the top of their scope but are initialized with undefined. When console.log(x) is called before the initialization, x is hoisted but not yet assigned the value 10, so it outputs undefined. After the initialization, x holds the value 10.
Concept:
- Hoisting: Variable declarations are moved to the top of the scope, but the initialization happens in place.
2. Hoisting with Function Declaration
Question:
console.log(foo());
function foo() {
return "Hello!";
}
Output:
Hello!
Explanation:
Function declarations are hoisted in their entirety, including the function body. So, even though foo() is called before the function definition, it works as expected because the function is fully hoisted to the top.
Concept:
- Function Hoisting: Entire function declarations (including the body) are hoisted to the top of the scope.
3. Hoisting with let and const
Question:
console.log(a);
let a = 5;
Output:
ReferenceError: Cannot access 'a' before initialization
Explanation:
Variables declared with let and const are hoisted but enter a "temporal dead zone" (TDZ) from the start of the block until they are initialized. This means that even though the declaration is hoisted, accessing a before its initialization will throw a ReferenceError.
Concept:
-
Temporal Dead Zone (TDZ): Variables declared with
letandconstare hoisted but cannot be accessed before initialization.
4. Hoisting with var inside a Function
Question:
function test() {
console.log(a);
var a = 10;
console.log(a);
}
test();
Output:
undefined
10
Explanation:
Within the function test(), the var declaration of a is hoisted to the top of the function. So, the first console.log(a) outputs undefined because the variable is hoisted but not yet initialized. After initialization, the second console.log(a) prints 10.
Concept:
-
Function Scope Hoisting: Inside a function, variables declared with
varare hoisted to the top of the function, initialized asundefined.
5. Hoisting with Multiple var Declarations
Question:
console.log(a);
var a = 10;
var a = 20;
console.log(a);
Output:
undefined
20
Explanation:
JavaScript allows multiple var declarations in the same scope, but only the first declaration is hoisted. The initial console.log(a) logs undefined due to hoisting, and the last console.log(a) logs 20 because the second assignment overwrites the first one.
Concept:
-
Multiple Declarations with
var: Multiplevardeclarations in the same scope are allowed but only the final assignment takes effect.
6. Hoisting with Function Expressions
Question:
console.log(foo);
var foo = function() {
return "Hello!";
};
console.log(foo());
Output:
undefined
Hello!
Explanation:
In this case, foo is declared using a function expression. The variable foo is hoisted to the top and initialized with undefined. Therefore, the first console.log(foo) outputs undefined. Once the function is assigned to foo, the second console.log(foo()) successfully calls the function, outputting "Hello!".
Concept:
- Function Expressions and Hoisting: Only the variable declaration is hoisted, not the function body. The function is assigned later in the code execution.
7. Hoisting with const Declaration
Question:
console.log(b);
const b = 30;
Output:
ReferenceError: Cannot access 'b' before initialization
Explanation:
Like let, variables declared with const are hoisted but are in the temporal dead zone (TDZ) until initialized. Accessing b before it is initialized results in a ReferenceError.
Concept:
-
Hoisting and
const: Variables declared withconstare hoisted but are not accessible before initialization due to TDZ.
8. Hoisting with Function Declarations and Variable Declarations
Question:
function hoist() {
console.log(a);
var a = 10;
console.log(a);
}
var a = 20;
hoist();
console.log(a);
Output:
undefined
10
20
Explanation:
- Inside
hoist(),ais hoisted as a local variable, soconsole.log(a)printsundefinedfirst. After assignment,abecomes10. Outside the function, the globalais unaffected and retains its value of20. - Hoisting ensures that the local
ainhoist()is treated separately from the globala.
Concept:
- Local vs Global Scope: Variable hoisting applies within function scope and does not affect the global scope.
9. Hoisting with Arrow Functions
Question:
console.log(foo);
var foo = () => {
return "Arrow Function!";
};
console.log(foo());
Output:
undefined
Arrow Function!
Explanation:
Similar to function expressions, when using arrow functions, the variable foo is hoisted but remains undefined until it is initialized. So, the first console.log(foo) prints undefined, and the second console.log(foo()) works after foo is assigned the arrow function.
Concept:
- Arrow Function Hoisting: Arrow functions behave like function expressions, where only the variable is hoisted, not the function body.
10. Hoisting with let and var in Loops
Question:
for (var i = 0; i < 3; i++) {
setTimeout(() => console.log(i), 1000);
}
for (let j = 0; j < 3; j++) {
setTimeout(() => console.log(j), 1000);
}
Output:
3
3
3
0
1
2
Explanation:
- For
var i, the variableiis hoisted and shared across all iterations. By the time thesetTimeoutcallback runs, the loop is done andihas the value3. - For
let j,letis block-scoped, so each iteration of the loop gets a new copy ofj. Therefore, when thesetTimeoutcallback runs, it prints the correct values (0,1,2).
Concept:
-
Loop Scoping with
varvslet: Variables declared withvarare hoisted and shared across loop iterations, whileletcreates a new binding for each iteration.
These output-based questions on hoisting will help you understand how JavaScript manages variable and function declarations in its execution context. Hoisting plays a crucial role in understanding the behavior of code, especially when dealing with var, let, const, and functions.
Top comments (0)