# Hoisting in JavaScript

> <https://scotch.io/tutorials/understanding-hoisting-in-javascript>

\ <br>

## What is Hoisting?

* JavaScript mechanism where variables and function declarations are **moved to the top of their scope** before code execution.
  * no matter where functions and variables are declared, they are moved to the top of their scope regardless of whether their scope is global or local.

\ <br>

## undefined vs ReferenceError

<br>

### `undefined`

* In JavaScript, an undeclared variables is assigned the value `undefined` at execution and is also of type of undefined.

<br>

### `ReferenceError`

* In JavaScript, a ReferenceError is thrown when trying to access a previously undeclared variable.

<br>

*The behavior of JavaScript when handling variables becomes nuanced because of hoisting!*

\ <br>

## Hoisting variables

* all `undeclared variables` are **global variables**

ex)

```javascript
function hoist() {
  a = 20;
  var b = 100;
}

hoist();

console.log(a);
/*
Accessible as a global variable outside hoist() function
Output: 20
*/

console.log(b);
/*
Since it was declared, it is confined to the hoist() function scope.
We can't print it out outside the confines of the hoist() function.
Output: ReferenceError: b is not defined
*/
```

<br>

### `var`

> function scoped

ex)

```javascript
console.log(hoist); // Output: undefined

var hoist = 'The variable has been hoisted.';
```

* JavaScript has hoisted the variable declaration

<br>

### `let`

> block scope

ex1)

```javascript
console.log(hoist); // Output: ReferenceError: hoist is not defined ...

let hoist = 'The variable has been hoisted.';
```

ex2)

```javascript
let hoist;

console.log(hoist); // Output: undefined
hoist = 'Hoisted'
```

* We should **declare** then **assign** our variables to a value before using them!

<br>

### `const`

> Introduced in ES6 to allow **immutable variables**

ex1)

```javascript
const PI = 3.142;

PI = 22/7; // Let's reassign the value of PI

console.log(PI); // Output: TypeError: Assignment to constant variable.
```

ex2)

```javascript
console.log(hoist); // Output: ReferenceError: hoist is not defined

const hoist = 'The variable has been hoisted.';
```

ex3)

```javascript
const PI;
console.log(PI); // Ouput: SyntaxError: Missing initializer in const declaration
PI=3.142;
```

* the variable is hoisted to the top of the block
* must be both declared and initialized before use.

\ <br>

## Hoisting functions

<br>

#### JavaScript functions

1. Function declarations
2. Function expressions

<br>

### Function declarations

> Hoisted completely to the top

ex)

```javascript
hoisted(); // Output: "This function has been hoisted."

function hoisted() {
  console.log('This function has been hoisted.');
};

```

<br>

### Function expressions

> Not hoisted

ex)

```javascript
expression(); //Output: "TypeError: expression is not a function

var expression = function() {
  console.log('Will this work?');
};
```

\ <br>

## Order of precedence

1. `Variable` assignment takes precedence over `function` declaration

   ```javascript
   var double = 22;

   function double(num) {
     return (num*2);
   }

   console.log(typeof double); // Output: number
   ```

   <br>
2. `Function` declarations take precedence over variable declarations

   ```javascript
   var double;

   function double(num) {
     return (num*2);
   }

   console.log(typeof double); // Output: function
   ```

<br>

*Function declarations are hoisted over variable declarations but not over variable assignments!*

\ <br>

## Hoisting classes

<br>

#### JavaScript Classes

1. Class declarations
2. Class expressions

<br>

### Class declarations

> Hoisted like function declarations

ex)

```javascript
var Frodo = new Hobbit();
Frodo.height = 100;
Frodo.weight = 300;
console.log(Frodo); // Output: ReferenceError: Hobbit is not defined

class Hobbit {
  constructor(height, weight) {
    this.height = height;
    this.weight = weight;
  }
}
```

* you have to declare a class before you can use it

<br>

### Class expressions

> Not hoisted like function expressions

ex)

```javascript
var Square = new Polygon();
Square.height = 10;
Square.width = 10;
console.log(Square); // Output: TypeError: Polygon is not a constructor

var Polygon = class {
  constructor(height, width) {
    this.height = height;
    this.width = width;
  }
};
```


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://chloe-codes1.gitbook.io/til/web/javascript/09_hoisting_in_javascript.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
