Hoisting - JavaScript Core Concepts
Tags: codenewbie, javascript, beginners, tutorial
Published: 2022-10-26 17:03:46

The **Section 2:** ***Functions & Methods*** of my **JavaScript Core Concepts** Series is divided into 6 Parts:

Part 1 Functions
Part 2 Classes
Part 3 Methods
Part 4 Callback Functions
Part 5 Scope
**Part 6 Hoisting**

# Hoisting: Variables vs Functions & Classes 
## Part 1 What is Hoisting?
= Here are a few different definitions of Hoisting: 
1. One of many operations a JS interpreter performs in the background

2. Variable/Function Declarations are hoisted to top of the Scope 
= Hoisting only moves the Declaration 
→ Any Assignments are left in place

3. Mental image to help us illustrate why we can access Functions & Variables before they are defined 

4. Picture how code is reorganized before Execution

### During Execution
= When Engine is actually executing our code 
→ Our Function & Variable Declarations: No longer there at all 
→ They have already been declared in a previous run

### Impact of Hoisting
= Hoisting Functions & Variables is reason why we can use some of them before they are actually declared 
→ Function & Variable Declarations are pulled to top of their scope 
Try to access them: They’ve already been declared

…

## Part 2 Hoisting Variables
### JS Variables’ Behaviour 
= 2 Parts
1. A Declaration 
2. An Initialisation/Assignment

= Even when you declare and assign a Variable in one line like this: `var name = 'Angeline'`
→ The JS engine still treats this line of code as 2 separate statements
→ It treats it as if you wrote this:
```
var name;
name = 'Angeline';
```

#### What are the impacts of Block Scope?
1. ES6 gives 2 new Variable Declaration keywords: `let` and `const`
= Difference between `let` and `const`
→ Variables declared with ES6 Keywords are block-scoped 

2. They are accessible only in code block they are defined in 
= A code block
→ Separated by curly braces

3. Variables created with `let` or `const` are not hoisted 
= Their definition is not pulled to the top like Variables declared with `var`

#### `var` Variable Declarations
= `var` Variable Declarations are hoisted AND fully initialized
→ With a Value Assignment of `undefined` by default 

##### Variable Declared w/in a Scope
= Belongs to that Scope 

##### Regardless of Location of Variable Declaration w/in a Scope
= All Variable Declarations are moved to top of their Scope (Global or Local)
→ This is called Hoisting 

#### `let` Variables Declarations
= `let` Variable Declarations cannot be read/written until they are *fully* initialized
→ When are they fully initialized? Where they are actually declared in the code 
→ `let` Variable Declaration is hoisted, but not initialized with `undefined` value (which is done by default with `var` variables)
→ `let` Declarations are not hoisted like `var` Declarations

#### `const` Variable Declarations
= Same behaviour as `let` variables 

### Hoisting In Action
= Variable/Function is not physically moved 
→ Hosting is just a model describing what the JS engine does behind the scenes 

### What is Hoisted?
= (`var`) Variable & Function Declarations are hoisted 
→ But Variable & Function Assignments are left in their place
→ *Even if* the Declaration and Assignment happen in the same line of code as in: `var name = 'Angeline'`

#### Reference before Declaration
= If you reference a Variable/Function before its Declaration
→ Expect a `ReferenceError` to be thrown

#### Referenced before Assignment
= Except a Default Value of `undefined` to be the Output
→ If `var` is used

### Temporal Dead Zone
= Section from beginning of Block to actual Variable Declaration 

#### Purpose
= Mechanism that ensures better coding practice 
→ Forces you to declare a Variable before you use it 

#### Compilation
##### Definition 
= Internals of JS & how it actually works 
→ V8 Engine increases performance by compiling JS to machine code before executing it 

##### Application
= Engine makes multiple runs through our code 
→ 1 of the early runs: It will declare all Functions & Variables
→ So when the code is executed: They will already be defined

##### Reference Error Prevention
= Make sure you are using only `let` and `const` for Variable Declaration

…

## Part 3 Hoisting Functions
= Hoisting also affects Function Declarations

### Function vs Variable Hoisting
= Only Declaration of the Variable is pulled to the top 
→ Value Assignment: Stays where it is
→ Cannot access Value of a Variable the same way we can call Functions

### Function Declaration vs Expression 
= Difference: Check position of word `function` in the statement 
→ If `function` is very 1st thing in the statement: It is a Function Declaration
→ Not `function` is not the first thing: It is a Function Expression

### Hoisting of Declarations vs Expressions
#### Declarations 
1. Hoisted completely 
= Entire Function’s body is moved to the top
→ Allows you to call a Function *before* it has been declared 

2. JS Engine
= Moves Declaration & its contents 
→ To beginning of the Scope
	
#### Expressions 
= Are not hoisted 
→ When a Function is assigned to a Variable 
Rules are the same as Variable Hoisting 

= Only the Declaration is moved
→ While the Assignment is left in place

#### Caution w/ Function Expressions 
= Variable Declaration will be hoisted
→ But Function assigned to Value not hoisted
→ Function will not be Hoisted

= Cannot be used before it is read
→ Actual Assignment of the Function as a Value stays where it is 
→ So if we try to call the Function, we will get an Error 

…

## Part 5 Hoisting Priority
1. Function Declaration 
2. Variable Declaration 
= Assignments: Variable *or* Function, are not hoisted, so are read later, and will overwrite Function and Variable Declaration Values

### Create Function w/ Variable Assignment 1st
= Will still be read after Function Declaration

#### Code Example
```
var showState = function() {
	console.log(“Idle”);
};

function showState() {
	console.log(“Ready”);
}

showState();
```
= This above code is interpreted by the JS Engine like this:
```
function showState() {
	console.log(“Ready”);
}

var showState;

showState = function(){
	console.log(“Idle”);
};

showState();
```

### Arrow Functions
= Interpreted the same way Function Expressions are in terms of hosting? 

…

## Part 4 Hoisting Classes
= Class Declarations 
→ Hoisted similarly as Variables declared with `let` statement

### Code Example
```
var user = new Person(‘Angeline’, 20);

class Person {
	constructor(name, age) {
		this.name = name;
		this.age = age;
	}
}
```
= `Person` Class being used before Declaration 
→ Produces a Reference Error: Similar to that in `let` Variables
 
#### Solution
= Must use the `Person` Class after the Declaration like this:
```
class Person {
	constructor(name, age) {#
		this.name = name;
		this.age = age;
	}
}

var user = new Person(‘Angeline’, 20);
console.log(user);
```

### Alternative Way to Create Classes
= Using a Class Expression 
→ Using `var`, `let`, or `const` Variable Declaration Statements

#### Code Example
```
console.log(typeof Person);

var user = new Person(‘Angeline’, 20);

var Person = class {
	constructor(name, age) {
		this.name = name;
		this.age = age;
	}
};
```
= `Person` Class is hoisted as a Function Expression 
→ But it cannot be used because its value is `undefined`

##### Solution
= Use `Person` Class after Declaration:
```
console.log(typeof Person);

var Person = class {
	constructor(name. age) {
		this.name = name;
		this.age = age;
	}
};

var user = new Person(‘Angeline’, 20);
console.log(user);
```