Function Hoisting ✨
Tags: javascript, functions, hoisting
Published: 2021-03-10 01:31:04

### Intro

In my last post, we discussed about hoising and  variable hoisting in detail. With the understanding of how variable hoisting works, let’s move on to function hoisting.

## Test Your Knowledge

Can you tell what will the following three sayHello() result in, and more importantly, explain why?

```javascript
sayHello()

function sayHello () {
  function hello () {
    console.log('Hello!')
  }
  
  hello()
  
  function hello () {
    console.log('Hey!')
  }
}
``` 

```javascript
sayHello()

function sayHello () {
  function hello () {
    console.log('Hello!')
  }
  
  hello()
  
  var hello = function () {
    console.log('Hey!')
  }
}
``` 


```javascript
sayHello()

var sayHello = function () {
  function hello () {
    console.log('Hello!')
  }
  
  hello()
  
  function hello () {
    console.log('Hey!')
  }
}

``` 

Answers are Hey!, Hello!, and the third one actually results in a TypeError.

Don’t worry if you didn’t guess these right. There will be a few more quiz at the end, and by then, you’ll find yourself more comfortable with function hoisting.

###Function Hoisting

Remember this example from variable hoisting?

```javascript
console.log(x)
var x

// undefined
``` 
The key here was that x was available before its declaration. The same logic applies to a function declaration.

```javascript
sayHello()

function sayHello () {
  console.log('Hello!')
}

// Hello!
``` 

In this example, I’m calling sayHello function before its declaration from line 3. Although it looks like I am calling a function that hasn’t even been declared, I can use it, and it prints out Hello!. This is thanks to function hoisting.


During the memory creation phase, the JavaScript engine recognised a function declaration by the function keyword and hoisted it — in other words, the JavaScript engine made the function available by putting it into the memory, before moving on. That’s why I could access the sayHello function prior to its declaration in the execution phase.

Alright, so what about this one? Can you tell what would the following code do?

```javascript
sayHello()

var sayHello = function () {
  console.log('Hello!')
}
``` 

Yep, that’s right — it results in TypeError, complaining that sayHello is not a function. Hmm… wait, what!?


In order to fully understand what’s happening behind the scene, we need to to know the difference between function declaration and function expression. Let’s spend a little bit of time on that first.

## Function Declaration vs Function Expression

There are two ways to define a function with the function keyword in JavaScript — function declaration and function expression.

A function declaration starts with the function keyword, followed by the name of the function (sayHello), then a block of code to be executed when the function is called ({ console.log('Hello!') }).

```javascript
function sayHello() {
  console.log('Hello!')
}

sayHello()

// Hello!
``` 

On the other hand, a function expression allows you to define a function without a name and as part of non-functional code blocks. A typical usage of a function expression is to assign a function to a variable. Below, I’m defining an anonymous function, that is, function without a name, (function () { console.log(Hello!) }) and assigning it to a variable (var sayHello =), so I can refer to the function via sayHello later on.

```javascript
var sayHello = function() {
  console.log('Hello!')
}

sayHello()

// Hello!
``` 
If I were to call these functions after they are defined, I can call them in the same way via sayHello() and both print out Hello!. However, when the JavaScript engine first sees them, it treats them in very different ways.


### Function Expressions are Not Hoisted

Let’s go back to example 2, which threw a TypeError: sayHello is not a function, and walk through what’s happening step by step from the JavaScript engine’s point of view.

```javascript
sayHello()

var sayHello = function () {
  console.log('Hello!')
}
``` 

During the memory creation phase, the JavaScript engine encounters the var keyword at line 3, at which point it expects a variable declaration to follow. Do you remember what the JavaScript engine does to a variable declaration? Yes, it hoists the variable with a value: undefined. And it doesn’t hoist the variable initiation.


Now… the TypeError starts to make sense. The variable declaration (var sayHello) was hoisted with a value undefined. However, the variable initialisation (= function () { console.log(Hello!) }) wasn’t hoisted. Therefore, when the execution reached line 1 and tried to call sayHello, it failed, because undefined is not a function! Only after the sayHello variable is assigned to a function expression during the execution at line 3, can we call the function by sayHello(). We can prove this with the following.


```javascript
console.log(sayHello)

var sayHello = function () {
  console.log('Hello!')
}

sayHello()

// undefined
// Hello!

``` 

#### Got it?
Please post any feedback, questions, or requests for topics. I would also appreciate 👏 if you like the post, so others can find this too.