Hoisting

What is hoisting ?

Hoisting is thought up as a general way of thinking about how execution contexts (specifically the creation and execution phases) work in JavaScript. It moves creation contexts above execution contexts. JavaScript only hoists declarations, not initializations.

Note: Conceptually, for example, a strict definition of hoisting suggests that variable and function declarations are physically moved to the top of your code, but this is not in fact what happens. Instead, the variable and function declarations are put into memory during the compile phase, but stay exactly where you typed them in your code.

Execution in detail

The statement var alpha = 6; is split up into following set of instructions/phases.

  1. [Declaration] Compiler will declare a variable alpha
  2. [Initialization] Compiler initialize alpha with undefined
  3. [Assignment] Compiler will assign variable alpha to value 6

A variable can only be accessed for execution after  intialization phase. All of this is only confined to particular lexical environment. Lexical environment maintains key/value map of all variables with names as key. All variable declarations (Declarations only) are pushed to the top of the execution in lexical environment execution.

  1. var is initialized to undefined. This allows the ability to use/assign/update/modify the variable without system throwing an error. It's value is undefined though.
  2. let/const is not initialized. As such, any reference to these variables would mean a compiler throwing error. This is the same for functions declared through const or classes.
  3. Functions created through function are available before because they are initialized to their definition at the start of a lexical environment.

Execution of variable declared by var by compiler
console.log('hello world');
console.log(x);
var x = 123;
var x; // Definition
x = undefined // Initialization
console.log('hello world');
// This still works because x because
// x initialisation has been moved up
console.log(x);
x = 123' // Assignment
Execution of variable declared by let/const by compiler
console.log('hello world');
console.log('hello world 1');
console.log(x);
let x = 123;
/**
 * Though variable is defined below
 * it is not yet available for access
 * as it is not initialized yet
 */
let x; // Definition only
// -- TEMPORAL DEAD ZONE --
console.log('hello world');
console.log('hello world 1');
// Below will throw error as variable is not initialised
console.log(x);
// -- TEMPORAL DEAD ZONE END --
x = 123' // Initialization & assignment

Experiments to show when a value is accessible.

References:

  1. Mozilla MDN entry
    https://developer.mozilla.org/en-US/docs/Glossary/Hoisting
  2. Nice article that explains lexical environment by Sukhjinder Arora
    https://blog.bitsrc.io/hoisting-in-modern-javascript-let-const-and-var-b290405adfda
  3. Article on what is temporal dead zone
    https://www.freecodecamp.org/news/what-is-the-temporal-dead-zone/
  4. Difference between declaraing & initialization of variable
    https://stackoverflow.com/questions/31714434/declaring-vs-initializing-a-variable/48052932