Introduction:
Learn the ins and outs of JavaScript hoisting with this comprehensive lesson. Discover the importance of hoisting, explore real-world examples, and understand best practices to write clean and efficient JavaScript code.
JavaScript hoisting is a behavior in the JavaScript language where variable and function declarations are moved to the top of their containing scope during the compilation phase,before the code is executed. This means that you can use variables and functions in your code before they are declared.
Here’s an example to illustrate hoisting:
Example
console.log(x); // undefined var x = 5; console.log(x); // 5
In the above example, the variable x is hoisted to the top of its containing scope during
the compilation phase. The first console.log(x) doesn’t result in an error, but it logs
undefined because the declaration is hoisted, but the assignment (x = 5) is not hoisted.
Function declarations are also hoisted:
Example
sayHello(); // "Hello, world!" function sayHello() { console.log("Hello, world!"); }
It’s considered good practice to declare variables at the top of their scope to avoid unexpected behavior due to hoisting and to make the code more readable and maintainable.
Let’s create a simple HTML page with JavaScript code that demonstrates hoisting.
Example
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>JavaScript Hoisting Example</title> </head> <body> <h1>JavaScript Hoisting Example</h1> <script> // Example 1: Variable Hoisting console.log("Example 1:"); // Using a variable before declaration console.log(x); // undefined var x = 5; console.log(x); // 5 // Example 2: Function Hoisting console.log("\nExample 2:"); // Using a function before declaration sayHello(); // "Hello, world!" function sayHello() { console.log("Hello, world!"); } // Example 3: Hoisting in Practice console.log("\nExample 3:"); var a = 10; function exampleFunction() { // The variable 'b' is hoisted to the top of the function scope console.log(b); // undefined var b = 20; console.log(a + b); // 30 } exampleFunction(); </script> </body> </html>
In this example:
Variable Hoisting (Example 1):
The variable x is used before its declaration. Due to hoisting, the declaration is moved to the top, and the first console.log(x) outputs undefined.
Function Hoisting (Example 2):
The function sayHello is used before its declaration. Hoisting moves the function declaration to the top, allowing it to be called before the actual declaration.
Hoisting in Practice (Example 3):
Demonstrates hoisting with a combination of variable and function declarations within a function scope.
The variable b is hoisted, and its usage before assignment results in undefined.
The final console.log statement outputs the sum of a and b.
When you open this HTML file in a browser, you should see the results in the browser’s
developer console. The output should demonstrate the behavior of hoisting in JavaScript.
Example
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>let and const Hoisting Example</title> </head> <body> <h1>let and const Hoisting Example</h1> <script> // Example 1: Hoisting with let console.log("Example 1:"); // Using a variable before declaration console.log(y); // ReferenceError: Cannot access 'y' before initialization let y = 10; // Variable 'y' is hoisted to the top of the block // Example 2: Hoisting with const console.log("\nExample 2:"); // Using a constant before declaration console.log(z); // ReferenceError: Cannot access 'z' before initialization const z = 20; // Constant 'z' is hoisted to the top of the block // Example 3: Temporal Dead Zone console.log("\nExample 3:"); // Variables in the temporal dead zone console.log(a); // ReferenceError: Cannot access 'a' before initialization let a = 30; // Constants in the temporal dead zone console.log(b); // ReferenceError: Cannot access 'b' before initialization const b = 40; </script> </body> </html>
In this example:
Let’s look at an example to illustrate this behavior:
Example
console.log(x); // undefined var x = 5; console.log(x); // 5
For example:
Example
var y = 10; console.log(y); // 10
In this case, both the declaration and initialization are in the same line, making the code more straightforward and less prone to errors.
complete code example
Let’s create a simple HTML page with JavaScript code to demonstrate hoisting and the non-hoisting of initializations. I’ll provide comments in the code to explain each step.
Example
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>JavaScript Initialization Hoisting Example</title> </head> <body> <h1>JavaScript Initialization Hoisting Example</h1> <script> // Example 1: Variable Declaration and Initialization Hoisting console.log("Example 1:"); // Using a variable before declaration and initialization console.log(a); // undefined var a = 10; console.log(a); // 10 // Example 2: Variable Initialization Not Hoisted console.log("\nExample 2:"); // Using a variable before declaration, but with initialization console.log(b); // ReferenceError: Cannot access 'b' before initialization var b = 20; // Example 3: Function Declaration and Initialization Hoisting console.log("\nExample 3:"); // Using a function before declaration and initialization sayHello(); // "Hello, world!" function sayHello() { console.log("Hello, world!"); } // Example 4: Function Initialization Not Hoisted console.log("\nExample 4:"); // Using a function before declaration, but with initialization sayHi(); // TypeError: sayHi is not a function var sayHi = function() { console.log("Hi!"); }; </script> </body> </html>
In this example:
Here’s an example demonstrating the recommended practice of declaring variables at the
top:
Example
// Declare variables at the top var globalVar = "I'm a global variable"; function exampleFunction() { // Declare function-scoped variables at the top var localVar1 = "I'm a local variable"; var localVar2; // ... rest of the function code ... // Use the declared variables console.log(globalVar); console.log(localVar1); console.log(localVar2); // Update local variables localVar1 = "Updated local variable"; localVar2 = "New local variable"; // ... rest of the function code ... } // Use the global variable console.log(globalVar); // Call the function exampleFunction();
In this example:
Here’s an updated example using let and const:
Example
// Declare variables at the top const globalConst = "I'm a global constant"; function exampleFunction() { // Declare block-scoped variables using let and const let localVar1 = "I'm a block-scoped variable"; const localVar2 = "I'm a block-scoped constant"; // ... rest of the function code ... // Use the declared variables console.log(globalConst); console.log(localVar1); console.log(localVar2); // ... rest of the function code ... } // Use the global constant console.log(globalConst); // Call the function
exampleFunction();
In this example, globalConst, localVar1, and localVar2 are declared at the top of their respective scopes, following the best practice of variable declaration.
complete code with explanation
Let’s create a simple HTML page with JavaScript code that demonstrates the best practice of declaring variables at the top. I’ll provide comments in the code to explain each step.
Example
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Declare Variables at the Top Example</title> </head> <body> <h1>Declare Variables at the Top Example</h1> <script> // Declare global variables at the top var globalVar = "I'm a global variable"; const globalConst = "I'm a global constant"; // Function demonstrating variable declaration at the top function exampleFunction() { // Declare function-scoped variables at the top var localVar1 = "I'm a local variable"; var localVar2; // Use the declared variables console.log(globalVar); console.log(localVar1); console.log(localVar2); // Update local variables localVar1 = "Updated local variable"; localVar2 = "New local variable"; // ... rest of the function code ... // Use global constant within the function console.log(globalConst); } // Use global variables outside the function console.log(globalVar); console.log(globalConst); // Call the function exampleFunction(); </script> </body> </html>
Explanation:
Let’s go through an example that illustrates the importance and uses of JavaScript hoisting:
Example
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>JavaScript Hoisting: Importance and Uses</title> </head> <body> <h1>JavaScript Hoisting: Importance and Uses</h1> <script> // Example 1: Variable Hoisting console.log("Example 1:"); // Using a variable before declaration console.log(x); // undefined var x = 5; console.log(x); // 5 // Example 2: Function Hoisting console.log("\nExample 2:"); // Using a function before declaration sayHello(); // "Hello, world!" function sayHello() { console.log("Hello, world!"); } // Example 3: Importance in Functions console.log("\nExample 3:"); function exampleFunction() { // Hoisted function declaration hoistedFunction(); // "I am hoisted!" function hoistedFunction() { console.log("I am hoisted!"); } // ... rest of the function code ... } // Call the function exampleFunction(); // Example 4: Importance in Variable Declarations console.log("\nExample 4:"); // Variable declared after its usage console.log(y); // undefined var y = 10; console.log(y); // 10 // Example 5: Practical Use Cases console.log("\nExample 5:"); // Practical use case: swapping values var a = 3, b = 7; console.log("Before swap: a =", a, "b =", b); // Swap values using a temporary variable var temp = a; a = b; b = temp; console.log("After swap: a =", a, "b =", b); </script> </body> </html>
Explanation:
Quiz to test your understanding of JavaScript hoisting.
Choose the correct option for each question. Answers and explanations are provided below.
JavaScript Hoisting Quiz:
a) Lifting heavy objects in JavaScript
b) Moving variable and function declarations to the top of their containing scope during
compilation
c) Creating higher-order functions in JavaScript
d) Animating elements on a webpage
a) const
b) let
c) var
d) function
Example
console.log(z);
var z = 8;
console.log(z);
a) Error: z is not defined
b) undefined and 8
c) 8 and 8
d) 0 and 8
a) var
b) let
c) const
d) function
function myFunction() {
console.log(a);
var a = 42;
console.log(a);
}
a) undefined and 42
b) Error: a is not defined
c) 42 and 42
d) 0 and 42
Answers:
1-b) Moving variable and function declarations to the top of their containing scope
during compilation.
2-c) var
3-b) undefined and 8
4-b) let
5-a) undefined and 42
Explanations:
1-Hoisting is the process of moving variable and function declarations to the top of
their containing scope during the compilation phase.
2-The var keyword is used for variable declaration and is subject to hoisting.
3-When using var, the declaration is hoisted, but the initialization is not. Therefore,
console.log(z) outputs undefined, and console.log(z) outputs 8 after the variable is
assigned.
4-Unlike var, let is block-scoped and not hoisted in the same way. It is hoisted to the
top of its block but is not initialized until the declaration statement.
5-In the function myFunction, the variable a is hoisted to the top of the function scope.
The first console.log(a) outputs undefined, and the second console.log(a) outputs 42
after the variable is assigned within the function.
Example
console.log(firstName);
let firstName = “John”;
console.log(firstName);
a) undefined and “John”
b) Error: firstName is not defined
c) null and “John”
d) 0 and “John”
a) Function expressions
b) Anonymous functions
c) Arrow functions
d) Function declarations
Example
var x = 10;
if (true) {
var x = 20;
}
console.log(x);
a) 10
b) 20
c) Error: x is not defined
d) undefined
a) Variable declarations using let are hoisted to the top of their block.
b) Function declarations are completely hoisted, including both name and implementation.
c) Hoisting only applies to variable and function declarations, not to variable
assignments.
d) Variables declared with const are hoisted in the same way as variables declared with
let.
a) To improve code readability
b) To prevent hoisting-related issues
c) Both a and b
d) Neither a nor b
Answers:
1-a) undefined and “John”
2-d) Function declarations
3-b) 20
4-d) Variables declared with const are hoisted in the same way as variables declared with
let.
5-c) Both a and b
Explanations:
1-When using let, the variable is hoisted to the top of its block but is not initialized
until the declaration statement. Therefore, the first console.log(firstName) outputs
undefined, and the second console.log(firstName) outputs “John” after the variable is
assigned.
2-Function declarations are hoisted entirely, including both the function name and its
implementation. This is not the case for function expressions, anonymous functions, or
arrow functions.
3-In the given code snippet, the variable x is hoisted to the top of the function scope,
and the value is modified within the if block. Therefore, the output is 20.
4-The false statement is d) Variables declared with const are hoisted in the same way as
variables declared with let. Variables declared with const are hoisted, but unlike var,
they are not initialized with undefined and remain in the “temporal dead zone” until the
actual declaration.
5-Declaring variables at the top of their scope in JavaScript is beneficial for both
improving code readability and preventing potential hoisting-related issues. It allows
developers to have a clear understanding of variable scope and reduces the chances of
unintentional variable shadowing.
Example
var a = 10;
function exampleFunction() {
console.log(a);
var a = 20;
console.log(a);
}
exampleFunction();
a) undefined and 20
b) Error: a is not defined
c) 10 and 20
d) 20 and 20
a) var
b) let
c) const
d) Both b and c
Example
console.log(getName());
function getName() {
return “John”;
}
a) Error: getName is not defined
b) undefined
c) John
d) null
a) It has no effect on the order of execution.
b) Code is executed from top to bottom, but hoisting may cause variables and functions to
be available before their declarations.
c) Code is executed in reverse order, starting from the bottom.
d) Hoisting rearranges the code to execute functions first, followed by variable
declarations.
a) To prevent variable assignments before declarations.
b) To optimize code execution.
c) To delay the execution of functions.
d) To provide a time limit for variable declarations.
Answers:
1-a) undefined and 20
2-b) let
3-c) John
4-b) Code is executed from top to bottom, but hoisting may cause variables and functions
to be available before their declarations.
5-a) To prevent variable assignments before declarations.
Explanations:
1-In the exampleFunction, the variable a is hoisted to the top of the function scope. The first console.log(a) outputs undefined, and the second console.log(a) outputs 20 after the variable is assigned within the function.
2-Unlike var, let declarations are not hoisted to the top of their scope. Variables declared with let are hoisted to the top of their block but are not initialized until the declaration statement.
3-Function declarations are hoisted entirely, including both the function name and its implementation. Therefore, calling getName() before its declaration still works, and the output is John.
4-Hoisting does affect the order of execution in the sense that declarations are moved to
the top during the compilation phase. However, the actual order of execution remains
top-to-bottom.
5-The “temporal dead zone” is a period during the execution of a program where variables declared with let and const exist but are not initialized. This prevents accessing the variables before their actual declarations and helps catch potential issues related to variable usage before initialization.
Mozilla Developer Network (MDN):