DEV Community

Adil Naeem
Adil Naeem

Posted on

Hoisting in JavaScript

When it comes to JavaScript, some concepts can feel overwhelming and frustrating, often tempting us to give up halfway through the learning journey. But don’t worry—I’m here to simplify things, making it easy for anyone, even beginners, to grasp how JavaScript truly works.

Let’s start by breaking down and mastering one of the core concepts: Hoisting.

Hoisting

Hoisting is a concept in core JavaScript which refers to the process in which interpreter (transforms or interprets a high-level programming code into code that can be understood by the machine (machine code) or into an intermediate language that can be easily executed as well.) moves the declarations of variables, functions, classes and imports to the top of their scope before the execution of code.

Whenever a JavaScript code executed, it runs in the "Execution context" in two phase.

  1. Memory Phase (Creation Phase).
  2. Code Execution Phase.

Memory Phase

In this phase, JavaScript scans the code and allocates memory for variables, functions, and classes before actually running the code. During this phase:

Function Declarations: The entire function is stored in memory, making it available to be called even before the line of code appears.

Variables with var: Variables declared with var are assigned a default value of undefined. The variable is hoisted, but it won't hold its actual value until the Execution Phase.

Variables with let and const: These are also hoisted but remain uninitialized (in a "temporal dead zone"). They cannot be accessed before their declaration, leading to a ReferenceError if you try.

Class Declarations: Classes are hoisted, but like let and const, remain in the "temporal dead zone" until their declaration is reached. Accessing them earlier will throw a ReferenceError.

Arrow Functions: These are treated like variables and not hoisted as regular functions. They behave like variables declared with const.

Code Execution Phase

In this phase, the JavaScript engine starts executing the code line by line. Now, it assigns actual values to the variables and runs the functions.

For Function Declarations: Since functions are fully hoisted during the memory phase, you can call them anytime in the code, even before their declaration.

For Variables (var, let, const): Variables declared with var will now be assigned their values. However, let and const only get initialized in this phase, and accessing them before initialization will still result in errors.

For Classes: Similarly, classes only get initialized here and trying to instantiate them before this phase will throw an error.

console.log(x); // undefined (var is hoisted with default value)
console.log(y); // ReferenceError (let is in "temporal dead zone")
console.log(z); // ReferenceError (const is in "temporal dead zone")

var x = 5;
let y = 10;
const z = 20;

greet(); // "Hello!" (Function is hoisted)
function greet() {
  console.log("Hello!");
}

arrowFunc(); // TypeError: arrowFunc is not a function (arrow function not hoisted)
const arrowFunc = () => console.log("Hello from arrow function");

Enter fullscreen mode Exit fullscreen mode

Top comments (0)