JS Demystified 02 — Function Hoisting
A humble attempt to demystify tricky concepts in JavaScript

JS Demystified Series

Intro
In my last post, we discussed 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?
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?
The key here was that x
was available before its declaration. The same logic applies to a function declaration.
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?
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!') }
).
N.B. You should declare functions as stand-alone or inside functional code blocks. Declaring function inside non-functional code blocks is not encouraged as the behaviour differs between different browsers. For more information, head over to ECMAScript 2017 — B.3.3Block-Level Function Declarations Web Legacy Compatibility Semantics.
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.
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.
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.
Wrap-up
Hopefully you are more familiar with function hoisting now. As I promised, here are some more quiz to test your understanding of function hoisting. As always, answers at the end of the post.
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.
Thanks, and see you next time!
// Answers to example 4 and 5Hello!
Hello!