Closure and Encapsulation in JavaScript | Simplified

What is Closure and when can we really use it?

To understand Closure, we need to know about 2 simple concepts in JavaScript: nested functions and returning a function.

In JavaScript, we can have nested functions. The inner function has access to the outer function’s variables and parameters.

Let’s check the following example:

function greetPerson(name) {
const message = 'Hello';

function displayMessage() {
console.log(`${message} ${name}!`);
}

displayMessage();
}

greetPerson('Alex'); // Hello Alex!

In this example, the inner function displayMessage can access the variable message declared in the outer function and the parameter name of the outer function.

Besides declaring and invoking an inner function inside the outer function, we can also return the inner function so that it can be invoked from outside.

Let’s see an example of this:

function greetPerson(name) {
const message = 'Hello';

function displayMessage() {
console.log(`${message} ${name}!`);
}

return displayMessage;
}

const displayMessageFunction = greetPerson('Alex');

console.log(typeof(displayMessageFunction)); // function
displayMessageFunction(); // Hello Alex!

In this example, the inner function displayMessage is returned by the outer function, so the type of displayMessageFunction variable is function. When we invoke that function, the displayMessage is being called and so the Hello Alex! message will be displayed.

After we understand this 2 concepts, the “definition” of closure is pretty simple.

Closure means that an inner function has access to the variables and the parameters of it’s outer function even after the outer function has returned.

Let’s see another example where we can see exactly how closure can be used:

function counterFunction() {
let counter = 0;

function increaseCounter() {
return counter += 1;
}

return increaseCounter;
}

// counter reffers to the increaseCounter returned by the counterFunction
const counter = counterFunction();

console.log(counter()); // 1
console.log(counter()); // 2
console.log(counter()); // 3
console.log(counter()); // 4

As the definition suggests, the inner function increaseCounter has access to the counter variable declared in the outer function counterFunction.

An inner function does not keep a separate copy of an outer variable, but it reference the outer variable. In other words, the value of the counter will be changed if you change it using the inner function.

The outer function counterFunction also returns a reference to the increaseCounter inner function, so when we call it, the actual value of the counter variable will be changed. In this way, we can see that the counter variable has a new incremented value after every counter() call.

We can use closure to achieve encapsulation in JavaScript. This can be accomplished by hiding detail implementation. In this way, we can create private variables and functions.

Let’s check the following example, where we want to encapsulate some data using only functions and objects:

const counter = (function () {
let privateCounter = 0;

function changeBy(val) {
privateCounter += val;
}

function increaseCounter() {
changeBy(1);
}

function decreaseCounter() {
changeBy(-1);
}

function decreaseCounter() {
return privateCounter;
}

return { increaseCounter, decreaseCounter, getCounterValue };
})();

console.log(counter.getCounterValue()); // 0

counter.increaseCounter();
counter.increaseCounter();

console.log(counter.getCounterValue()); // 2

counter.decreaseCounter();

console.log(counter.getCounterValue()); // 1

In this example, we only expose increaseCounter, decreaseCounter and getCounterByValue because they are included in the returned object. The privateCounter variable as well as the changeBy function cannot be accessed from outside, since they are not part of the returned object.

We can control the counter’s value from outside, only by calling increaseCounter and decreaseCounter, and we can get the value by calling the getCounterValue function, which behaves like a getter.

In this way, we are able to simulate the public and private access specifiers and achieve encapsulation.

This is a very powerful concept in software development since it prevents unintended modifications to variables and functions that should remain private.

That’s all!

Thank you for taking the time to read this article on Closure in JavaScript. I hope it has helped you understand better this important concept and how it can be used to achieve encapsulation and create private variables and functions!

--

--

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store