DEV Community

Cover image for JavaScript Hoisting
Dylan Oh
Dylan Oh

Posted on • Edited on

JavaScript Hoisting

In this article, we are going to discuss about hoisting in JavaScript.

Hoisting, is a process that happens during the creation of execution context, which will move the declarations of variables and functions up to the top of the context. Let's start with an example:

hello();

function hello(){
    return "Hello World";
}
Enter fullscreen mode Exit fullscreen mode

If you are familiar with JavaScript, you know that this is not going to throw an error. What is happening when during the creation of global execution context is that the engine will move the variable declaration (in this case the function "hello") up to the context when it sees "function" keyword. Which also means, before the code is executed, it will look something like this:

function hello(){
    return "Hello World";
}
hello();
Enter fullscreen mode Exit fullscreen mode

It moves that declaration up. Therefore, memory is allocated to store this function declaration before the code execution. How about variables that is not a function declaration?

console.log(text)

var text = "Hello World!"
Enter fullscreen mode Exit fullscreen mode

Let's say I have this piece of code that tries to print out variable "text" before it gets declared and defined. What will it print out?

undefined
Enter fullscreen mode Exit fullscreen mode

Undefined. When the engine sees "var", it will know to leave a piece of memory for this variable, but it doesn't know that what value has been assigned to this variable. Therefore, when the declaration of the variable is hoisted, "undefined" gets assigned to this variable as default. This is the reason why error was not thrown, but printed out "undefined" instead.

You have also seen this way of defining a function:

hello();

var hello = function(){
    return "Hello World";
}
Enter fullscreen mode Exit fullscreen mode

This is a function expression. What if we do this? Are we going to get the "Hello World" printed out correctly?

VM592:1 Uncaught TypeError: hello is not a function
    at <anonymous>:1:1
Enter fullscreen mode Exit fullscreen mode

Hmm... ok, so the engine does not know that this is a function. Remember? When the engine sees "var", it is going to move the declaration of "hello" up and gives an undefined default value. If you try to call it, it is going to tell you that this is not a function. Let's print out what hello is before assigning that function to it.

console.log(hello);

var hello = function(){
    return "Hello World";
}
Enter fullscreen mode Exit fullscreen mode
undefined
Enter fullscreen mode Exit fullscreen mode

Just now we mentioned that when the execution context is created, the variables declaration get hoisted. Let's try this:

function hello(){
    console.log("1: " + text)
    var text = "Hello World"
    console.log("2: " + text)
}

hello()
Enter fullscreen mode Exit fullscreen mode

What can we expect here?

1: undefined
2: Hello World
Enter fullscreen mode Exit fullscreen mode

Alright, this is aligned with what we have just discussed. Let's give a value to the "text" in global scope.

var text = "Am I printed?"
function hello(){
    console.log("1: " + text)
    var text = "Hello World"
    console.log("2: " + text)
}

hello()
Enter fullscreen mode Exit fullscreen mode

Again, what will you expect it to print out?

1: undefined
2: Hello World
Enter fullscreen mode Exit fullscreen mode

Still, 1: is undefined. When hello() is called, a new execution context is created, and "text" variable is hoisted to the top of that hello() context, therefore, it is not aware of the assigned value from global execution context.

Let's try one more thing, we remove the declaration of variable within hello():

var text = "Am I printed?"
function hello(){
    console.log("1: " + text)
}

hello()
Enter fullscreen mode Exit fullscreen mode
1: Am I printed?
Enter fullscreen mode Exit fullscreen mode

Yes, you are printed. Scope chain, right? (JavaScript Scoping)

Do you think all these will cause confusion when we are writing JavaScript code?

In order to make our code more predictable, we can use "let" and "const" in ES6. They don't get hoisted.

hello();

const hello = function(){
    return "Hello World";
}
Enter fullscreen mode Exit fullscreen mode
Uncaught ReferenceError: hello is not defined
    at <anonymous>:1:1
Enter fullscreen mode Exit fullscreen mode

Yup, this feels better. There are some unexpected behaviours that might happen when you just started learning JavaScript (like type coercion). However, understanding these concepts will definitely make you a better JavaScript developer.

Since we mentioned "let" and "const", I would also like to add on one more regarding block scope and function scope. When we use other languages, this is something that we would expect to throw error (we use groovy here as example):

if(someCondition)
{
    def someVar = "Can you see me? "
}
def newVar = someVar + "I cannot see you."
Enter fullscreen mode Exit fullscreen mode

This is because the variable is defined within the "block scope". What if we do this in JavaScript?

var someCondition = true

if(someCondition)
{
    var hello = "Hello "
}

var helloWorld = hello + "World"

console.log(helloWorld)
Enter fullscreen mode Exit fullscreen mode
Hello World
Enter fullscreen mode Exit fullscreen mode

Error will not be thrown in this case for JavaScript. This is because "var" is only scoped by function and module. If you do this in a function, it will throw error.

function someFunction()
{
    var hello = "Hello "
}

var helloWorld = hello + "World"

console.log(helloWorld)
Enter fullscreen mode Exit fullscreen mode
VM1525:6 Uncaught ReferenceError: hello is not defined
    at <anonymous>:6:18
Enter fullscreen mode Exit fullscreen mode

What if we also want to have block scope for {}?

Use "let" and "const".

let someCondition = true

if(someCondition)
{
    let hello = "Hello "
}

let helloWorld = hello + "World"

console.log(helloWorld)
Enter fullscreen mode Exit fullscreen mode
VM1566:8 Uncaught ReferenceError: hello is not defined
    at <anonymous>:8:18
Enter fullscreen mode Exit fullscreen mode

That's it for this article, hope you enjoyed!


Do follow me for more future articles on web design, programming and self-improvement 😊

Follow me on Medium

Oldest comments (0)