Page Content

Posts

What are the JavaScript Hoisting with Code Example

JavaScript Hoisting

The conventional view of JavaScript as a solely “interpreted language” is identified as a prevalent misunderstanding. JavaScript engines frequently use a compilation step prior to code execution, while they can also use an interpreter. This compilation is an important stage that occurs prior to (and occasionally during) execution, rather than being a distinct, upfront process as in some languages. The Engine, Compiler, and Scope are all involved in this process. Code is broken up into tokens (Tokenizing/Lexing), structured (Parsing into a syntax tree), and generated as executable code by the compiler.

Declarations are processed by the JavaScript engine during this compilation stage. The sections of your code that declare new values and give them names are called declarations, and they basically specify the program’s structure. Before the statements that genuinely “make something happen” are carried out, they are processed. The engine’s Scope object maintains a lookup list of all declared identifiers (variables and functions) for a specific scope and imposes accessibility guidelines on them.

This conduct, in which declarations are handled prior to execution, is referred to metaphorically as hoisting. Before the code executes, the declarations appear to have been conceptually “moved” to the top of their contained scope.

Let’s look at how different types of declarations are handled:

var Variable Hoisting: When you use var to declare a variable, its declaration is handled during compilation and is accessible conceptually at the top of its global scope or function. The assignment, or assigning a value to the variable, stays in the code precisely where you wrote it. A var variable is present in the scope but will have an undefined value if you attempt to access it before the line where it is assigned a value. “Partial early activation” is the term used for this.

Consider this code:

console.log(carName); // Output: undefined
var carName = “Volvo”; // Declaration and assignment
console.log(carName); // Output: Volvo
The engine effectively sees this during the compilation phase and sets up the variable declaration:
var carName; // Declaration processed early
console.log(carName); // carName exists, but has default value undefined
carName = “Volvo”; // Assignment happens here during execution
console.log(carName); // carName now has the assigned value

Function Declaration Hoisting: Function declarations, which are defined with the function keyword, are handled differently than var. During the compilation stage, the function’s declaration and definition (the code inside) are both processed. “Instantly fully initialised” describes them. This enables you to call a function declaration in your code before the line that contains it. The term “early activation” describes this.

Example:

greet(); // This works! Output: Hello there!

function greet() { // Function declaration
console.log(“Hello there!”);
}

The greet function is defined and made available in its scope during compilation, so it is already recognised and ready to use when the execution reaches the greet() call on the first line.

Var vs. let and const Hoisting: Newer JavaScript versions introduced variables specified with let and const, which operate differently when it comes to hoisting. They are not initialised in the same manner as var variables, even though their declarations are similarly handled during the compilation stage and linked to their block scope. A ReferenceError will occur if a let or const variable is accessed before the line where it is declared within its block. The Temporal Dead Zone (TDZ) is the time frame from the beginning of the block till the declaration line is reached. The TDZ’s variables are in the “Uninitialised” state.

Example with let:

// console.log(count); // This line would cause a ReferenceError due to the TDZ
let count = 10; // let declaration and assignment
console.log(count); // Output: 10

Count is not useful until the declaration line is run, even if the engine parsed the let count declaration at the beginning of the block. Var, on the other hand, would return undefined.

Function Expressions: Function declarations are raised in a different manner than function expressions, which are produced as part of an expression and frequently assigned to a variable (let func = function() {… }). They adhere to the variable to which they are assigned’s hoisting guidelines. The function definition is not accessible until the assignment line is reached, even though the variable declaration is hoisted (initialised to undefined) if it is assigned to a variable. The variable is subject to the TDZ if it is assigned to let or const. Only when the execution flow reaches the function’s defining line are function expressions generated.

Example with a function expression assigned to let:

// sayHi(); // This would cause a ReferenceError because sayHi is in the TDZ

let sayHi = function(name) { // Function expression assigned to a let variable
console.log(Hello, ${name});
};

sayHi(“Alice”); // This works

Essentially, the engine recognises every declaration and links it to its scope during the compilation stage. Although function and variable declarations are theoretically made available at the top of their scopes (“hoisted”), they behave differently when it comes to initialisation (functions are fully initialised, while variables are undefined). Though they are more stringent and prohibit access prior to their declaration line because of the Temporal Dead Zone, let and const declarations are also handled. The key to comprehending variable accessibility and the distinctions between function declaration and expression and var, let, and const is knowing this pre-execution processing. Because let and const have a block scope and more predictable variable access behaviour than var strongly advise using them.