A practical example of Javascript closures

Juan Dalmasso
Webtips
Published in
4 min readAug 19, 2020

Most developers today, know about closures in Javascript. Don’t be sad if you don’t, it’s not something you generally use on your every-day work (well, you may, but it’s not so common).

If you haven’t heard yet about closures, I recommend you to read this article: https://medium.com/javascript-scene/master-the-javascript-interview-what-is-a-closure-b2f0d2152b36

Closures are something that many companies would like you to know before working for them, therefore, chances are they’ll ask you something related with this topic, or even more, they could make you write a practical example of it.

On this story, I’m gonna tell you about a small function I was asked to develop on an interview a while ago, that involved the use of closures for its solution.

Let’s start with the premise:

Can you write a function that will solve the following test case?

let result = sum(1)(2)(3)();console.log(result === 6 ? 'SUCCESS' : 'ERROR');

The function we need to create will sum the values sent as a parameter and will accumulate them. Also, it will return another function for the next value to be passed on. If we don’t send any value to it, it will return the accumulated value.

It looks fairly simple at first, but let’s take a look into it:

const sum = (value) => {
let accum = 0;
if (value) {
accum += value;
const innerSum = (value) => { /*TODO*/ };
} else {
return accum;
}
};
console.log(sum());
0

That’s a good start. First, we create the function called sum that will take a value as a parameter. If that value exists, we will sum the value to the accum and return a function to keep adding values (TODO).

Let’s continue with the function:

const sum = (value) => {
let accum = 0;
if (value) {
accum += value;
const innerSum = (innerValue) => {
if (innerValue) {
accum += innerValue;
return innerSum;
} else {
return accum;
}
};
return innerSum;
} else {
return accum;
}
};
console.log(sum(1)(2)(3)());
6

Cool, that works. Let’s recap: we called this new function innerSum, and, like the parent one, it receives a value and sums it. If what we sent to the function is a valid value, we will sum it to our accum and return the function itself, and if not, we will return the total value of the accumulator.

As you can see, the closure was created inside the original sum function. The returned innerSum will maintain the lexical scope of the parent function, and therefore, it will keep the value of accum even after the initial function is not being used anymore.

A closure is the combination of a function bundled together (enclosed) with references to its surrounding state (the lexical environment). In other words, a closure gives you access to an outer function’s scope from an inner function. In JavaScript, closures are created every time a function is created, at function creation time.
https://medium.com/javascript-scene/master-the-javascript-interview-what-is-a-closure-b2f0d2152b36

Great, it does what we want, but I think we can improve it more. Let’s refactor it a little bit:

const sum = (value) => {
let accum = 0;

const innerSum = (innerValue) => {
if (innerValue) {
accum += innerValue;
return innerSum;
} else {
return accum;
}
};
return innerSum;
};
console.log(sum(1)(2)(3)());
5 // WRONG!

As you can see, we got rid of the initial check for the value, since we would always send at least 2 values (first one a number, last one undefined). But something’s not quite right, as you can see, the result is “5” instead of “6”. What happened here? At first sight, we can imagine that the first value was cut off somehow, but why?

Well, what we are initially doing, is to create the acccum in 0 and then return the function, without adding the first number. An easy way to overcome this, is to initialise the accum with the first value we send. Also, we can add some validation to make sure a value is always sent as a first parameter:

const sum = (value) => {
let accum = value;

if (!value) {
return 0;
}
const innerSum = (innerValue) => {
if (innerValue) {
accum += innerValue;
return innerSum;
} else {
return accum;
}
}
return innerSum;
};
console.log(sum());
0
console.log(sum(1)(2)(3)());
6

Amazing! Now it looks much better. As you may be thinking, there’s still a lot of room for improvement, but we will leave it as it is and you can think by yourself on how we can refactor it or make it more efficient.

Next steps:

  • Validate that the value sent is a number.
  • Allow the use of “0” as valid parameter.

Conclusion

Closures are an easy way to achieve cool things like this one, but the most useful implementation, is to make global variables “private” using a similar method. This will let you avoid unwanted modifications to the variables inside of the scope you define, but you’ll need to provide a mechanism to modify those variables from the outside. Extra care needs to be taken when doing it though.

To read next

If you’re an advanced programmer, the semantic of the function above may have resulted familiar to you. It’s because the technique of having a series of nesting function is called a curry in Javascript. If you want to learn more about them, here’s an interesting story:

https://medium.com/better-programming/currying-inside-javascript-a19f29600880

--

--