Navigate back to the homepage

Closure for beginner part 2; Nested function.

Haja Andriamaro
October 1st, 2019 · 2 min read

Follow along from Part I

In my previous article, we have covered the concept of Lexical Scope, a building bloc to understand closure. We have seen that we can use a variable to keep track of the digits that make up the phone number. We also worned that at this stage, there is a serious flaw in our code. In this article, we will talk about the existing flaw, and how to fix it with nested function, the other building bloc to understand and use closure.

What’s the flaw?

At this stage we have the following code

1// intialise the number to an empty string
2let dialledNumber = '';
3
4function phonePad (digit) {
5 // concatanate each new digit to build the dialled number
6 dialledNumber = dialledNumber.concat(digit);
7 console.log('The phone number to call is: ' + dialledNumber);
8}
9
10phonePad('0'); // The phone number to call is: 0
11phonePad('6'); // The phone number to call is: 06
12phonePad('5'); // The phone number to call is: 065

It does the job, we are able to store each new digit in the “dialledNumber” variable. And because “dialledNumber” is in the Lexical scope of phonePad() we are all good …

However, “dialledNumber” is acting as a global variable here (accessible/mutable by any intermediat scripts). It is therefore “unprotected”. It means that “dialledNumber” can be accidently (or not) used by intermediat script for other puroposes. If that happen, our phone pad logic would be broken. The line 13 below will break the app

1// intialise the number to an empty string
2let dialledNumber = '';
3
4function phonePad (digit) {
5 dialledNumber = dialledNumber.concat(digit);
6 console.log('The phone number to call is: ' + dialledNumber);
7}
8
9phonePad('0'); // The phone number to call is: 0
10phonePad('6'); // The phone number to call is: 06
11// next line will mess up our phone pad memory
12dialledNumber = "Random assigment"
13phonePad('5'); // The phone number to call is: Random assigment5

Protecting the pad memory

Therefore, we need to find a way to protected “dialledNumber” variable. We can do just that moving it inside phonePad(). This will make it accessible only from inside phonePad(), and take it off the global scope now. In other words, “dialledNumber” become a private variable to phonePad()

So lets try that here

1function phonePad (digit) {
2 // intialise the number inside phonePad
3 let dialledNumber = '';
4
5 dialledNumber = dialledNumber.concat(digit);
6 console.log('The phone number to call is: ' + dialledNumber);
7}
8phonePad('0'); // The phone number to call is: 0
9phonePad('6'); // The phone number to call is: 6
10phonePad('5'); // The phone number to call is: 7

But wait! what happened? the phonePad memory is gone !

Here is what is happening. Each time we call phonePad(), javascript creates a brand new instance of that function. The previous instance just went to what is called “garbage collector”, or just garbage if you want. Then, how do we get back that memory while still keeping “dialledNumber” private?

We can do that in two folds.

  • Create a nested function
  • Create a reference to the nested function.

Nested function & Reference

It name says it all. A nested function, is a function inside (nested) another function. So we will nest another function inside phonePad(). But that’s not enough, we also have to follow extra steps to make the phone pad working. Following are all the steps that we will follow :

  1. Nest an anonymous function inside phonePad().
  2. Remove “digit” as phonePad(digit) argument, and set it as the anonymous function(digit) argument instead.
  3. Return the anonymous function.
  4. Return the dialledNumber variable from the anonymous function scope
  5. Assign phonePad() function to a “pad” variable
  6. Use the variable “pad” to serve as reference and to pass the selected digits

The code should look like this

1function phonePad () {
2 // intialise the number string
3 let dialledNumber = "Phone number is: ";
4 // declare the nested function receiving digits as argument
5 // And return it
6 return function (digit){
7 // concatanate each new digit to build the phone number
8 dialledNumber = dialledNumber.concat(digit);
9 // return the concatanated digits
10 return dialledNumber
11 }
12}
13// assign phonePad() to a variable that
14// will serve as reference/link
15const pad = phonePad()
16// send each new nmuber to pad()
17// and display the phone number
18console.log(pad(0))
19console.log(pad(6))
20console.log(pad(5))
21console.log(pad(7))

And the output

Console closure error 2

Voila! Remember, by default functions in javascripts can not hold sate (information) beyond its instance life cycle. What we did here is to enable just that by:

  1. Protecting “dialledNumber”, making it a “private” variable that can hold state.
  2. Nesting a function that take care of updating of the state (protected variable “dialledNumber”)
  3. Keeping phonePad() instance “alive” by using a reference to its nested function.

The 3 above steps allow us to create a function that is able to hold a private state (the phone number). Which would not be possible whithout closure. This is what Closure is all about :)

You probably still wonder how Closures are being used concretly to make things happen in “real” app …

That will be the subject of the last article for this serie for a perfect Closure ;)

More articles

Closure for beginner part 1; Lexical scope.

One the first thing I have being told as I started learning to code is

September 30th, 2019 · 3 min read

How to find, and make your first contribution to an open source project.

Making your first contribution can be intimidating. But it does not need to be so, really ...

October 14th, 2019 · 4 min read
© 2021 Haja Andriamaro
Link to $https://twitter.com/haja_andriamLink to $https://github.com/Haja-andriLink to $https://www.linkedin.com/in/haja-andriamaro/