# Hoisting

## Summary


In many languages, variables and functions have to be declared upfront before they can be used later in code. Attempting to use them before declaration would result in an error. 

In JavaScript, it's possible to use variables and functions before they're explicitly declared later in code. This feature of JavaScript is called **Hoisting**. In a sense, the declarations are "hoisted" to the top of the code. 

While hoisting is a useful feature, in the interest of code readability and maintenance, it's perhaps a good practice to put declarations before they're used.

## Discussion

### Could you illustrate hoisting with an example?

In the code `console.log(x); var x = 1;`, the variable `x` is used before it's declared. JavaScript allows this because of hoisting. 

Hoisting is also possible for functions. In the code `add(3, 4); function add(a, b) { return a + b; }`, the function `add()` is called before it's declared. Again, this is possible due to hoisting. 

Hoisting can occur in any execution context. JavaScript has three types of execution contexts: global, function, and eval. 


### Is hoisting moving a declaration to the top of the scope?

One common (and incorrect) explanation of hoisting is that the JavaScript engine moves variable and function declarations to the top of their scope. Variable declarations are initialized with value `undefined`. In reality, the JavaScript engine doesn't move code to the top this way. 

The correct explanation lies in understanding **execution context**. This is the environment in which the code runs. Such an environment encapsulates `this`, variables, objects and functions that are accessible. Execution context is created in two phases: creation phase and execution phase. 

During the creation phase, memory is allocated for variables and functions in that scope. The entire function body is in memory but it's not executed. Likewise, variables become available in memory but are not initialized. It's only later, during the execution phase, that initializing variables and calling of functions happen.  


### What can be hoisted?

Variables and functions are hoisted. Functions can be called earlier in the code even if their declarations happen later. It's interesting to note that if a variable and a function have the same name (a practice that should be discouraged), variable initialization takes precedence over function declaration. If the variable in uninitialized, function declaration takes precedence. 

Function expressions are not hoisted. Function expressions take the form `var a = function () {...}`. Variable `a` is hoisted, which means that it's initialized to `undefined`. Thus, we can't make the call `a()` since the variable is not initialized with the function object. Similarly, arrow functions, which are of the form `var a = () => ...`, are not hoisted. 

Class declarations are "hoisted" only in the sense that memory is allocated but not initialized with the class object. With class expressions, the variable is hoisted but it's initialized to `undefined`. For example, `var Square = new Polygon(); var Polygon = class { ... }` won't work because `Polygon` is `undefined`. This effectively means that we can't instantiate objects without putting the declaration first. 


### Could you share more details on hoisting variables?

JavaScript has this default behaviour that a variable initialized without a declaration is automatically declared with global scope. This happens during the execution phase of execution context, not during the creation phase. Therefore, such variables are not hoisted. Hoisting applies only to explicitly declared variables. For example, hoisting works for `console.log(a); var a = 1;` but not for `console.log(b); b = 1;`. For this reason, it's recommended to explicitly declare variables. 

Variables declared with keywords `let` or `const` are "hoisted" in the sense that memory is allocated during the creation phase of execution context. Thus, during execution phase, JavaScript engine won't complain that they're undefined. However, the engine will still throw a reference error when the code attempts to use them before they're properly initialized. Unlike the `var` keyword, `let` and `const` keywords don't initialize variables with `undefined`. The solution is therefore to declare before using such variables. Hoisting is not useful for `let` and `const`.

## Milestones

1995

**JavaScript** is announced as a dynamic scripting language that can run within a web browser. Two years later, a more standardized form of JavaScript, called **ECMAScript** is published by ECMA International. 

Oct  
2010

A video on YouTube explains JavaScript hoisting with examples. This shows that the term "hoisting" is in use by 2010, if not earlier. 

Jun  
2015

ECMA International releases *ECMAScript® 2015 Language Specification*. This specification uses the term "hoisting". It's said that prior standards didn't use the term explicitly. Hoisting provides us a metaphor to think about execution contexts.