Understanding JavaScript Hoisting and Closures

Hey - Nick here! This page is a free excerpt from my $99 course JavaScript Fundamentals.

If you want the full course, click here to sign up and create an account.

I have a 30-day satisfaction guarantee, so there's no risk (and a ton of upside!) in signing up for this course and leveling up your JavaScript developer skills today!

In this tutorial, you will learn how to understand and implement JavaScript hoisting and JavaScript closure.

Table of Contents

You can skip to a specific section of this tutorial using the table of contents below:

What is JavaScript Hoisting?

JavaScript hoisting is a concept that allows you to refer to JavaScript functions and variables before they have been created.

As you'll recall from our section on JavaScript functions, hoisting is applied to functions that are created with the function keyword. Here is an example:

printHello();

function printHello(){

	console.log('Hello');

}

Even though the function printHello is being invoked prior to its declaration, the function still runs as intended. Hello is printed to the browser console.

How does hoisting work? Before JavaScript code is executed, it is first compiled. Compilation is a series of steps taken by a programming language to make its statements interpretable by the computer.

During this compilation step, JavaScript moves all function and variable declarations to the start of the script. This causes hoisting!

Hoisting also works for variables. However, it only hoists the variable declarations, not the values assigned to the variable. If you attempt to reference a variable prior to its declaration in a JavaScript file, it will return the undefined value.

Here is an example:

console.log(var1);

var var1 = "This is the value assigned to var1!";

This logs undefined to the browser console.

Another important concept to understand with respect to variable hoisting is that it only works with the var keyword. If you attempt to hoist a variable with the const or let keyword, your browser will return an error message.

Return to the Table of Contents

What is JavaScript Closure?

JavaScript closures are arguably one of the more difficult components of the JavaScript programming language. My hope is that I will be able to elucidate the closure concept for you in this tutorial.

A JavaScript closure is the ability to access a parent-level scope from a child scope even when the parent function has been terminated. Closures occur when one JavaScript function is nested inside of another.

Let's see JavaScript closures in action.

To start, let's create a function called innerFunction that will act as the child function. The innerFunction function will have a variable called innerVariable.

function innerFunction(){

	const innerVariable = "Inner variable";

}

Next, let's nest innerFunction inside another function called outerFunction. The outerFunction function will have a variable called outerVariable.

function outerFunction(){

	const = outerVariable = "Outer variable";

}

Now let's nest innerFunction inside of outerFunction:

function outerFunction(){

	const outerVariable = "Outer variable";


    function innerFunction(){


    	const innerVariable = "Inner variable";


    }

}

Next, let's add two console.log statements inside of innerFunction - one for the innerVariable variable and one for the outerVariable variable:

function outerFunction(){

	const outerVariable = "Outer variable";


    function innerFunction(){


    	const innerVariable = "Inner variable";


    	console.log(outerVariable);


    	console.log(innerVariable);


    }

}

Finally, let's add a function call to innerFunction within outerFunction. This means that each time outerFunction is invoked, it will also invoke innerFunction:

function outerFunction(){

	const outerVariable = "Outer variable";


    function innerFunction(){


    	const innerVariable = "Inner variable";


    	console.log(outerVariable);


    	console.log(innerVariable);


    }


    innerFunction();

}

Executing the outerFunction function will now cause the following output to be logged to the console:

Outer variable

Inner variable

So how do closures come into play here?

Well, a closure would occur when you do not call innerFunction from inside of outerFunction, but instead at a later point inside of your program.

To do this, we need to make two small changes to our JavaScript code.

First, we need to add a return statement to outerFunction that actually returns innerFunction when outerFunction is executed.

Second, we need to run outerFunction and assign this to a new variable.

Here are these changes in action:

function outerFunction(){

	const outerVariable = "Outer variable";


    function innerFunction(){


    	const innerVariable = "Inner variable";


    	console.log(outerVariable);


    	console.log(innerVariable);


    }


    return innerFunction; //Note that there are no round brackets here

}

theInnerFunction = outerFunction()

theInnerFunction has now been assigned the innerFunction function from inside of outerFunction.

What do you think happens when we attempt to run theInnerFunction? After all, it will attempt to console.log the outerVariable variable, which should only be accesible within the outerFunction function because of the scoping that we learned about in our last lesson.

If you run theInnerFunction, the following output will be logged to the console:

Outer variable

Inner variable

Woah - so we have found a way for function-scoped variables to be accessed outside of the function! This is exactly what developers mean when they refer to a closure.

You might be wondering why closures might be useful. After all, this basic example that we have just worked through seems unnecessarily complicated.

Well, closures can be used to create private variables, which are an advanced concept that we will be learning more about later in this course.

If closures still seem complicated to you, do not worry. We will be referring to them many more times throughout the rest of this course.

Return to the Table of Contents

Final Thoughts

In this tutorial, you learned about JavaScript hoisting and closure. Specifically, we discussed how hoisting allows you to refer to JavaScript variables and functions prior to their declaration, and how closures allow you to access function-scoped variables outside of that specific function.