All writing

JavaScript Hoisting

JavaScript

When a variable is declared with var, the declaration is lifted up or hoisted to the top of the enclosing function. The initialization of variable remains where it is, but the definition of the variable moves to the top of the function.

Variable declared with var can be used anywhere in the enclosing function. If the initialization code has not run yet, then the value of the variable may be undefined, but there will not be any errors even if the variable is used before initialization. This can be sometimes a disadvantage as it can be a source of bugs. In that case, using let to declare a variable will get an actual error instead of just getting an undefined value.

However, hoisting has some advantages. It gives us the advantage that no matter where functions and variables are declared, they are moved to top of their scope regardless of whether their scope is global or local. This allows us to call functions before initializing them.

In summary, the following behaviors of JavaScript could be regarded as hoisting:

1. Being able to use variable’s value in its scope before the line it is declared. (“Value hoisting”)
2. Being able to reference a variable in its scope before the line it is declared, without throwing a ReferenceError, but the value is always undefined. (“Declaration hoisting”)
3. The declaration of the variable causes behavior changes in its scope before the line in which it is declared.
4. The side effects of a declaration are produced before evaluating the rest of the code that contains it.

HoistableDeclaration (only includes function, function*, async function and async function*) are hoisted with type 1 behavior; var declaration is hoisted with type 2 behavior; Lexical declarations (let, const and class) are hoisted with type 3 behavior; import declarations are hoisted with type 1 and type 4 behavior.

Lexical declarations can be sometimes referred to as non-hoisting, because of the temporal dead zone which strictly forbids any use of the variable before its declaration. Temporal dead zone (TDZ) is the area of a block where a variable is inaccessible until it is completely initialized with a value.

While inside the TDZ, the variable has not been initialized with a value, any attempt to access it will result in a ReferenceError. The variable is initialized with a value when execution reaches the place in the code where it was declared. If no initial value was specified with the variable declaration, it will be initialized with a value of undefined.

This differs from var variables, which will return a value of undefined if they are accessed before they are declared.

{
//TDZ starts at beginning of scope
console.log(bar); // "undefined"
console.log(foo); // ReferenceError: Cannot access "foo" before initialization
var bar = 1;
let foo = 2; // End of TDZ (for foo)
}

To prevent errors, variables should be accessed outside of the temporal dead zone. Also, it’s a good practice to declare all variables at the beginning of every scope.