JavaScript Hoisting: Understanding the Elevator of Declarations


Ever wondered why you can use a variable or call a function before it’s declared in your code? That’s hoisting in action! 

1. Variable Hoisting:

Variables declared with var are hoisted to the top of their scope during the compilation phase. However, only the declaration is hoisted, not the initialization. So, if you try to use the variable before it’s assigned, you get undefined.

2. Function Hoisting:

Both function declarations and function expressions are hoisted, but they behave differently. Function declarations are completely hoisted, while function expressions only hoist the variable declaration, not the function assignment.

3. Block-level Scope:

With the introduction of let and const, we got block-scoped variables. Unlike var, these don’t hoist to the entire function or global scope, only within their block.

Understanding hoisting is key to writing predictable and error-free JavaScript. It affects the order in which your code is executed, and can sometimes lead to unexpected behavior if not handled carefully.

JavaScript hoisting is a behavior that occurs during the compilation phase of the code execution process. In JavaScript, before the code is executed, the JavaScript engine moves variable and function declarations to the top of their containing scope. This process is known as hoisting.

Here’s a breakdown of how hoisting works for variables and functions:

Variable Hoisting:

Variable declarations using the var keyword are hoisted to the top of their scope, but only the declaration is hoisted, not the initialization. If a variable is initialized later in the code, it will still have the default value of undefined until the assignment is reached.

console.log(x); // undefined

var x = 5;

console.log(x); // 5

The above code is interpreted as follows during hoisting:

var x; // Declaration is hoisted

console.log(x); // undefined

x = 5; // Initialization remains in place

console.log(x); // 5

Note: ES6 introduced the let and const keywords, which have block-level scope and do not exhibit the same hoisting behavior as var.

console.log(y); // ReferenceError: Cannot access ‘y’ before initialization

let y = 10;

Function Hoisting:

Function declarations are also hoisted to the top of their scope, including both the function name and the function body. This means you can call a function before its actual declaration in the code.

sayHello(); // Hello, World!

function sayHello() {

 console.log(“Hello, World!”);

}

During hoisting, the code is rearranged like this:

function sayHello() {

 console.log(“Hello, World!”);

}

sayHello(); // Hello, World!

However, function expressions are not hoisted in the same way as function declarations. Only the variable declaration is hoisted, not the function assignment.

// This will throw an error

sayHi(); // TypeError: sayHi is not a function

var sayHi = function() {

 console.log(“Hi!”);

};

The above code is interpreted as:

var sayHi;

sayHi(); // TypeError: sayHi is not a function

sayHi = function() {

 console.log(“Hi!”);

};

In summary, hoisting in JavaScript involves moving variable and function declarations to the top of their containing scope during the compilation phase. Understanding hoisting is crucial for writing predictable and error-free JavaScript code.

Coding Exercises for Hoisting

Exercise 1: Variable Hoisting

Description: Predict the output of the following code:

console.log(a);

var a = 5;

console.log(a);

Steps:

  1. Understand the hoisting behavior for variable declarations with var.
  2. Predict the output by considering the hoisting phase.

Solution:

// Output:

// undefined

// 5

Exercise 2: Variable Hoisting with let

Description: Predict the output of the following code:

console.log(b);

let b = 10;

console.log(b);

Steps:

  1. Recognize the differences in hoisting behavior between var and let.
  2. Predict the output based on the hoisting rules for let.

Solution:

// Output:

// ReferenceError: Cannot access ‘b’ before initialization

Exercise 3: Function Hoisting

Description: Predict the output of the following code:

hello();

function hello() {

 console.log(“Hello!”);

}

Steps:

  1. Understand the hoisting behavior for function declarations.
  2. Predict the output considering the function declaration hoisting.

Solution:

// Output:

// Hello!

Exercise 4: Function Expression Hoisting

Description: Predict the output of the following code:

hi();

var hi = function() {

 console.log(“Hi!”);

};

Steps:

  1. Recognize that function expressions are not hoisted in the same way as function declarations.
  2. Predict the output based on the hoisting behavior of function expressions.

Solution:

// Output:

// TypeError: hi is not a function

Exercise 5: Hoisting in a Function

Description: Predict the output of the following code:

function example() {

 console.log(x);

 var x = 20;

 console.log(x);

}

example();

Steps:

  1. Consider that hoisting occurs within the scope of a function.
  2. Predict the output based on the function scope hoisting.

Solution:

// Output:

// undefined

// 20

Exercise 6: Hoisting Order

Description: Predict the output of the following code:

var c = 30;

function order() {

 console.log(c);

 var c = 40;

 console.log(c);

}

order();

console.log(c);

Steps:

  1. Understand the order of hoisting for variable declarations in different scopes.
  2. Predict the output considering the hoisting order.

Solution:

// Output:

// undefined

// 40

// 30

Exercise 7: Hoisting in a Block

Description: Predict the output of the following code:

if (true) {

 console.log(y);

 let y = 50;

 console.log(y);

}

Steps:

  1. Recognize that let has block-level scope and does not exhibit the same hoisting behavior as var.
  2. Predict the output based on block-scoped hoisting.

Solution:

// Output:

// ReferenceError: Cannot access ‘y’ before initialization

Exercise 8: Hoisting and Function Expression

Description: Predict the output of the following code:

var greet = function() {

 console.log(“Welcome!”);

};

greet();

Steps:

  1. Recognize that function expressions are hoisted differently from function declarations.
  2. Predict the output considering the hoisting of the function expression.

Solution:

// Output:

// Welcome!

Exercise 9: Hoisting with Function Declaration Overriding

Description: Predict the output of the following code:

function example() {

 console.log(“First”);

}

example();

function example() {

 console.log(“Second”);

}

example();

Steps:

  1. Understand how function declarations are hoisted and potentially overridden.
  2. Predict the output based on the order of function declarations.

Solution:

// Output:

// Second

// Second

Exercise 10: Hoisting in a Nested Scope

Description: Predict the output of the following code:

function outer() {

 console.log(innerVar);

 if (true) {

 var innerVar = “Nested”;

 console.log(innerVar);

 }

 console.log(innerVar);

}

outer();

Steps:

  1. Recognize the hoisting behavior in nested scopes.
  2. Predict the output considering variable hoisting in nested functions.

Solution:

// Output:

// undefined

// Nested

// undefined

These exercises cover various aspects of hoisting in JavaScript, including variable hoisting, function hoisting, and the differences between var, let, and function expressions. Practice these exercises to enhance your understanding of JavaScript hoisting.

Quiz Questions:

Question: What is the purpose of hoisting in JavaScript?

A. Enhancing code readability

B. Optimizing code execution

C. Handling variable and function declarations before code execution

Answer: C. Handling variable and function declarations before code execution

Question: Which keyword has block-level scope in JavaScript and does not exhibit hoisting like var?

A. var

B. let

C. const

Answer: B. let

Question: What is the output of the following code?

console.log(b);

let b = 20;

console.log(b);

A. ReferenceError

B. undefined and 20

C. 20 and 20

Answer: A. ReferenceError

Question: Do variables declared with const exhibit hoisting?

A. Yes

B. No

Answer: B. No

Question: What happens during the hoisting phase for variable declarations with var?

A. Initialization is moved to the top of the scope

B. Only declaration is moved to the top of the scope

C. Entire variable assignment is moved to the top of the file

Answer: B. Only declaration is moved to the top of the scope

Question: What is the output of the following code?

console.log(c);

var c = 15;

console.log(c);

A. undefined and 15

B. ReferenceError

C. 15 and 15

Answer: A. undefined and 15

Question: In JavaScript, are function declarations hoisted before or after variable declarations?

A. Before

B. After

C. It depends on the specific scenario

Answer: A. Before

Question: What is the output of the following code?

sayHi();

function sayHi() {

  console.log(“Hi!”);

}A. Hi!

B. ReferenceError

C. undefined

Answer: A. Hi!

Question: Do function expressions assigned to variables get hoisted like function declarations?

A. Yes

B. No

Answer: A. Yes

Question: What is the output of the following code?

console.log(greet);

var greet = function() {

  console.log(“Greetings!”);

};

A. undefined

B. ReferenceError

C. Greetings!

Answer: A. undefined

Question: How does JavaScript handle the hoisting of duplicated function declarations?

A. Raises an error

B. Overwrites the previous declaration

C. Appends the new declaration

Answer: B. Overwrites the previous declaration

Question: What is the output of the following code?

var a = 10;

function example() {

  console.log(a);

  var a = 20;

  console.log(a);

}

example();

console.log(a);

A. undefined, 20, 10

B. 10, 20, 10

C. 10, undefined, 20

Answer: A. undefined, 20, 10

Question: Can you hoist a variable declared with let before its actual declaration?

A. Yes

B. No

Answer: B. No

Question: What is the output of the following code?

if (true) {

  console.log(d);

  let d = 25;

  console.log(d);

}

A. ReferenceError

B. undefined and 25

C. 25 and 25

Answer: A. ReferenceError

Question: What is the primary difference between var and let regarding hoisting?

A. let is not hoisted

B. var is not hoisted

C. Both var and let are hoisted in the same way

Answer: A. let is not hoisted

Question: What is the output of the following code?

console.log(x);

let x = 30;

console.log(x);

A. ReferenceError

B. undefined and 30

C. 30 and 30

Answer: A. ReferenceError

Question: What is the behavior of hoisting in a function with both variable and function declarations?

A. Function declarations are hoisted before variable declarations

B. Variable declarations are hoisted before function declarations

C. Both are hoisted in the order they appear in the code

Answer: C. Both are hoisted in the order they appear in the code

Question: What is the output of the following code?

function test() {

  console.log(y);

  var y = 35;

  console.log(y);

}

test();

A. undefined and 35

B. ReferenceError

C. 35 and 35

Answer: A. undefined and 35

Question: In what order are multiple function declarations in the same scope hoisted?

A. Bottom-up

B. Top-down

C. Random

Answer: B. Top-down

Question: What is the output of the following code?

function demo() {

  console.log(z);

  if (true) {

    var z = “Nested”;

    console.log(z);

  }

  console.log(z);

}

demo();

A. undefined, Nested, undefined

B. ReferenceError

C. undefined, Nested, Nested

Answer: A. undefined, Nested, undefined

Question: Can function declarations be hoisted inside block-level scopes?

A. Yes

B. No

Answer: A. Yes

Question: What is the output of the following code?

if (true) {

  console.log(h);

  function h() {

    console.log(“Inside if”);

  }

}

h();

A. Inside if, ReferenceError

B. ReferenceError, ReferenceError

C. Inside if, Inside if

Answer: A. Inside if, ReferenceError

Question: How does hoisting behave when there are multiple variable declarations with the same name?

A. Raises an error

B. Overwrites the previous declaration

C. Appends the new declaration

Answer: B. Overwrites the previous declaration

Question: What is the output of the following code?

console.log(i);

var i = 40;

console.log(i);

var i = 45;

console.log(i);

A. undefined, 40, 45

B. ReferenceError

C. undefined, 45, 45

Answer: A. undefined, 40, 45

Question: Can you hoist variables declared with var in a block-level scope?

A. Yes

B. No

Answer: A. Yes

Question: What is the output of the following code?

var j = 50;

function outerFunc() {

  console.log(j);

  if (true) {

    var j = 55;

    console.log(j);

  }

  console.log(j);

}

outerFunc();

console.log(j);

A. undefined, 55, 50

B. 50, 55, 50

C. 50, undefined, 55

Answer: A. undefined, 55, 50

Question: Can you hoist function declarations inside a function?

A. Yes

B. No

Answer: A. Yes

Question: What is the output of the following code?

function outerFunction() {

  console.log(innerVar);

  if (true) {

    var innerVar = “Inner”;

    console.log(innerVar);

  }

  console.log(innerVar);

}

outerFunction();

A. undefined, Inner, undefined

B. ReferenceError

C. undefined, Inner, Inner

Answer: A. undefined, Inner, undefined

Question: Can you hoist function expressions inside a function?

A. Yes

B. No

Answer: B. No

Question: What is the output of the following code?

function exampleFunc() {

  console.log(exampleVar);

  if (true) {

    var exampleVar = “Example”;

    console.log(exampleVar);

  }

  console.log(exampleVar);

  function exampleVar() {

    console.log(“Function Declaration”);

  }

}

exampleFunc();

A. undefined, Example, undefined

B. Function Declaration, Example, Function Declaration

C. ReferenceError

Answer: B. Function Declaration, Example, Function Declaration

Question: What does hoisting refer to in JavaScript?

A. Moving code to the top of the file

B. Moving declarations to the top of their scope during compilation

C. Enhancing code performance

Answer: B. Moving declarations to the top of their scope during compilation

Question: Which keyword is associated with block-scoped variables in JavaScript?

A. var

B. let

C. const

Answer: B. let

Question: What is the output of the following code?

console.log(a);

var a = 8;

console.log(a);

A. undefined and 8

B. 8 and 8

C. 8 and undefined

Answer: A. undefined and 8

Question: Do function expressions exhibit the same hoisting behavior as function declarations?

A. Yes

B. No

Answer: B. No

Question: What is the output of the following code?

hello();

function hello() {

  console.log(“Hello!”);

}

A. Hello!

B. ReferenceError

C. undefined

Answer: A. Hello!

Question: How are function expressions hoisted in JavaScript?

A. Only the variable declaration is hoisted

B. Both the variable declaration and the function body are hoisted

C. Function expressions are not hoisted

Answer: A. Only the variable declaration is hoisted

Question: What is the output of the following code?

console.log(z);

let z = 15;

console.log(z);

A. 15 and 15

B. undefined and 15

C. ReferenceError

Answer: C. ReferenceError

Question: In which order are variable declarations hoisted in JavaScript?

A. Bottom-up

B. Top-down

C. Random

Answer: B. Top-down

Question: What is the output of the following code?

var m = 25;

function demo() {

  console.log(m);

  var m = 30;

  console.log(m);

}

demo();

console.log(m);

A. undefined, 30, 25

B. 25, 30, 25

C. 25, undefined, 30

Answer: A. undefined, 30, 25

Question: Does hoisting occur in block-level scopes for variables declared with var?

A. Yes

B. No

Answer: A. Yes