JS Function Hoisting Concisely Explained 
Published: 2021-03-06 23:40:07


### Terms to Know
**Execution Context** (which is different from scope, btw) - an abstract concept where the code runs. First by parsing the code line by line and second, storing variables and the functions into memory. Two of the three contexts are `global` and `local` execution contexts. For good reads on execution context, check out the two articles in the reference section below.

**Declaration** (of a variable or function) - Example of variable declaration are `let a`, `const result`, while a function declaration is `function calcSquareFootage(x,y){ // code}. Declaration brings a thing into existence. Note that a `function expression` is hoisted differently and explained below. 

**Initializing** (variables only) - `a=1.567` or declare and initialize together: ‘const result = 234.53`. You can initialize in JS variables without declaring them using `let`, `const`, or the ghastly `var`. But doing so will cause a bug as the undeclared but initialized variable is now a globally accessed variable.  Initializing is often called an assignment. 

**Hoisting** - is a concept and not an actual process. All declarations (variable and function) are first placed into memory during the compile phase while initializing/assignment happens later. 

### Hoisting Functions
You can try these in your browser console. To clear the variables declarations and assignment, hard refresh this page.

**Rule of thumb** - declare named functions, function expressions, anonymous functions, or arrow functions before you invoke them. 

```javascript
addThreeNumbers(1, 10, 4564)  // successfully returns 4575 even if invoked before the function declaration 

// function declaration
function addThreeNumbers(x, y, z){
return (x + y + z)
}


multiplyThreeNumbers (1, 10, 4564) // Uncaught ReferenceError: multiplyThreeNumbers is not defined. 

// function expression is hoisted but assigned an `undefined` value rather then the function code
let multiplyThreeNumbers = function(x, y, z){
return (x * y * z)
} 


add(1, 10)  // Uncaught ReferenceError: Cannot access 'add' before initialization

//arrow function initialization is hoisted the same as a function expression, thus `add` is assigned undefined in this cause using ‘let add`  
let add = (x, y) => {return(x+y)}

```





### Order of Precedence in Hoisting is a Thing
What happens if you declare a function and a variable with the same name?

```javascript
let name = “Brad”

// notice function has same name as variable above
function name(firstName){  
return (`hi  ${firstName}`)
}

console.log(typeof name) // output is string
```

* Variable assignments before a function declarations
* But, function declarations before variable declarations

**Rule of Thumb** - don’t use the same name for a variable and a function


### References
[Understanding Execution Context and Execution Stack in Javascript](https://blog.bitsrc.io/understanding-execution-context-and-execution-stack-in-javascript-1c9ea8642dd0)
[Understanding JavaScript Execution Context and How It Relates to Scope and the `this` Context](https://levelup.gitconnected.com/learn-javascript-fundamentals-scope-context-execution-context-9fe8673b3164) 
[Hoisting Functions & Function Expressions](https://dmitripavlutin.com/javascript-hoisting-in-details/#5-function-declarations)