/ Javascript

Javascript closure in action

Who is this article intended for?

All folks who are working with javascript, learning javascript or have been using fancy javascript frameworks and platforms like angularjs, nodejs or even as basic as jQuery or if you plan to start writing javascript and transitioning from an object oriented languages like c# or you are a reader and like reading non-fiction articles 👻 ...

Javascript

Javascript is the most forgiving language I have ever come across. Everything just seems to work, well this can be dangerous, sometimes - if not always; We might end up writing something that works but may be very inefficient or even worst, after a long day's work, the script might seem perfect but the output may be equally bizarre. I agree, that javascript may be unintuitive, occasionally, even counterintuitive. Let's look at following example to see what I mean.

'use strict'

for (var i = 0; i < 10; i++) {
  console.log('"i" is equal to ' + i);
}

//Code 1.0

Can you guess, what output will it produce? You guessed it right.

It will produce following output
"i" is equal to 0
"i" is equal to 1
"i" is equal to 2
"i" is equal to 3
"i" is equal to 4
"i" is equal to 5
"i" is equal to 6
"i" is equal to 7
"i" is equal to 8
"i" is equal to 9

//Output 1.0

Pretty predictable right? Now lets add a tiny bit of complexity, we want to add a delay between the output prints. Meaning, we want to print 0 instantly, 1 after 1 sec, 2 after 2 sec and so on and so forth. This isn't much of a challenge, right? Following your intuitions you might write something similar

'use strict'

for (var i = 0; i < 10; i++) {
  setTimeout(function () {
    console.log('"i" is equal to ' + i + ' (after ' + i + ' secs)');
  }, (1000 * i));
}

//Code 1.1
And you would be expecting following output
"i" is equal to 0 (after 0 secs)
"i" is equal to 1 (after 1 secs)
"i" is equal to 2 (after 2 secs)
"i" is equal to 3 (after 3 secs)
"i" is equal to 4 (after 4 secs)
"i" is equal to 5 (after 5 secs)
"i" is equal to 6 (after 6 secs)
"i" is equal to 7 (after 7 secs)
"i" is equal to 8 (after 8 secs)
"i" is equal to 9 (after 9 secs)

//Assumed Output 1.1

If you though so, I won't blame you.

Above code will actually produce following output
"i" is equal to 10 (after 10 secs)
"i" is equal to 10 (after 10 secs)
"i" is equal to 10 (after 10 secs)
"i" is equal to 10 (after 10 secs)
"i" is equal to 10 (after 10 secs)
"i" is equal to 10 (after 10 secs)
"i" is equal to 10 (after 10 secs)
"i" is equal to 10 (after 10 secs)
"i" is equal to 10 (after 10 secs)
"i" is equal to 10 (after 10 secs)

//Actual output 1.1

Bizarre right? Didn't I say that javascript can be counterintuitive sometimes!

😮What just happened? -- Well, Meet Closure!

What you just encountered is called closure. Well, Don't be rude, say hello! Closure is a friend if understood and used wisely but a fearful enemy if left unnoticed.

Closure enables functions to remember its scope of execution. Meaning, it makes functions remember the variables and other functions it refers. Closure makes the referred variables and functions available, even after the scope is exited, latest values are reflected.

Simplest example of closure is following hello world example

'use strict'

//Following function returns a function which prints - Hello `name`!
function sayHelloTo(name){
   return function (){
       //This function "remembers" the name -- thanks to closure.
       console.log('Hello ' + name + '!');
   }
}

var helloWorld = sayHelloTo('World');
/*
   The closure enables the child function "remember" the "name" variable
   even after the parent scope has exited.
*/

//Prints out "Hello World!" in the console.
helloWorld();

//Code 1.2

produces

Hello World!

//output 1.2

Pretty neat right? And this is what happened with our first example, closure. Little bit cryptic, ain't it? Let me elaborate, javascript runs on a single thread, so it queues up tasks that needs differed execution, remember setTimeout - we used it in our first example? So what happened with the example is first the for loop executes and iterates for 10 times with value of i = 0 to 9, with each iteration it executes setTimeout block with appropriate value of i, meaning for i = 0 => setTimeout(<function>,0) for i = 1 => setTimeout(<function>,1000) and for i = 9 => setTimeout(<function>,9000). Now setTimeout is executed but the <function> goes through deferred execution, so the first <function> is executed only after the for loop is executed completely. So at the time when <function> executes, the for loop has already exited and final value of i is equal to 10. Now due to closure, <function> remembers the i and fetches the latest value, which is 10 and hence the cryptic output. What we learned is that the value of i is NOT COPIED for each iteration instead the reference is remembered.

How do I make it work then?

There are more then one way to get what we want. First lets look at IIFE.

Option 1: IIFE

IIFE (immediately-invoked function expression) are function expressions which are executed as soon as they are defined. For example

'use strict'
//The IIFE
(function (arguments) {
  /* Awesomeness goes here */
})();

//Code 1.3

As you can see that the function is invoked as soon as it is defined. So we can rewrite Code 1.1 as

'use strict'

for (var i = 0; i < 10; i++) {
  /*
     IIFE with a parameter i, this i parameter is different then i in
     the for loop. IIFE forces a new execution scope to be created
     and current *value* of the i in for loop is *copied* to the new
     scope
  */
  (function (i) {
    //i has *value* i (of for loop) at the time of invocation
    setTimeout(function () {
      console.log('"i" is equal to ' + i + ' (after ' + i + ' secs)');
    }, (1000 * i));
  })(i); //i of the for loop is passed as parameter, forcing new scope to be
  //created with current copy of i.
}

//Code 1.1.1

Option 2: Function.prototype.bind

The above example with IIFE looks quite complex and mouthful. As we now have an idea on how to solve the problem on hand, all we need to do is force create new scope and Function.prototype.bind can be used to do so.

'use strict'

for (var i = 0; i < 10; i++) {
  /*
      (<function(i)>).bind(this, i) forces a new scope to be created *copying*
      the current *value* of i
      
  */
  setTimeout((function (i) {
    console.log('"i" is equal to ' + i + ' (after ' + i + ' secs)');
  }).bind(this, i), (1000 * i));
}

// Code 1.1.2

This version is very much similar to Code 1.1, only difference is instead of setTimeout(<function>,timeout) we have setTimeout( (<function(i)>).bind(this, i), timeout). So instead of asking setTimeout to defer <function> we are asking it to defer a copy of <function> bound to current value of i.

Option 3: The ES6 way!

let is almost exactly same as var except the fact that it creates lexically scoped variables. Variables created declared with let have limited to the scope they are defined in, in case of for loop, for each iteration, new copy of i is created which limits to that particular iteration.

'use strict'
/*
   We are using `let` instead of `var`, `let` creates a `lexically` scoped
   variable i, meaning, for each iteration of for loop a new copy of i is
   created, so closure captures the `lexically` scoped reference
*/
for (let i = 0; i < 10; i++) {
  setTimeout(function () {
    console.log('"i" is equal to ' + i + ' (after ' + i + ' secs)');
  }, (1000 * i));
}

// Code 1.1.3

All of these three options produce following output

"i" is equal to 0 (after 0 secs)
"i" is equal to 1 (after 1 secs)
"i" is equal to 2 (after 2 secs)
"i" is equal to 3 (after 3 secs)
"i" is equal to 4 (after 4 secs)
"i" is equal to 5 (after 5 secs)
"i" is equal to 6 (after 6 secs)
"i" is equal to 7 (after 7 secs)
"i" is equal to 8 (after 8 secs)
"i" is equal to 9 (after 9 secs)

// Output for 1.1.1, 1.1.2, 1.1.3

A word of Caution

As you can see, closure are powerful, but as uncle ben once said ***"With great power comes great responsibility"***. Unnecessary usage of closure can make your code inefficient. Because every time a closure is created memory is consumed to store and maintain the references, sometimes this will result in poor quality program. So always make sure that you eliminate any unnecessary and unintended closures. For example, one should not write functions inside functions and access parent functions values when there are better ways to do the same thing. Because doing so would create unnecessary closure. Take a look at following example

'use strict'
function Car(make, model) {

  return{
    setMake: function (value) {
      make = value;
    },
    getMake: function () {
      return this.make;
    },
    setModel: function (value) {
      model = value;
    },
    getModel: function () {
      return model;
    },
    print: function () {
      console.log(make, model);
    }

  }
}

var skodaSuperb = Car('Skoda', 'Superb');
skodaSuperb.print();
skodaSuperb.setModel('Octavia');
skodaSuperb.print();

// code 1.4

output

Skoda Superb
Skoda Octavia
//output 1.4

This code heavily uses closures, but does not need to, there are better ways to do it, for example look at following example.

'use strict'
function Car(make, model) {
    this.make = make;
    this.model = model;

    this.setMake = function (make) {
      this.make = make;
    }
    this.getMake = function () {
      return this.make;
    }

    this.setModel = function (model) {
      this.model = model;
    }
    this.getModel = function () {
      return this.model;
    }

    this.print = function () {
      console.log(this.make, this.model);
    }
}

var skodaSuperb = new Car('Skoda', 'Superb');
skodaSuperb.print();

skodaSuperb.setModel('Octavia');
skodaSuperb.print();

// code 1.5

output

Skoda Superb
Skoda Octavia

//output 1.5

Above code is written in right direction and also looks fine, but if you take another look, you'd see that each function this.setMake, this.getMake, this.setModel, this.getModel and this.print creates a closure, which is clearly not required or used anywhere in the program. So it would be wise to remove them by following any of the two options

Option 1: Setting the prototype

It is wise to put the functions in the prototype, as shown below

'use strict'
function Car(make, model) {
    this.make = make;
    this.model = model;
}

/* attach functions to the prototype */
Car.prototype.setMake = function (make) {
  this.make = make;
}
Car.prototype.getMake = function () {
  return this.make;
}

Car.prototype.setModel = function (model) {
  this.model = model;
}
Car.prototype.getModel = function () {
  return this.model;
}

Car.prototype.print = function () {
  console.log(this.make, this.model);
}

var skodaSuperb = new Car('Skoda', 'Superb');
skodaSuperb.print();

skodaSuperb.setModel('Octavia');
skodaSuperb.print();

//code 1.5

output

Skoda Superb
Skoda Octavia

//output 1.5

Above code is what should be written ideally. No Unnecessary closure are created and all's well.

Option 2: Function.prototype.call (A cleaner way)

This method is very similar to option 1, actually we are writing option 1 is a more readable way.

'use strict'
function Car(make, model) {
  this.make = make;
  this.model = model;
}

(function () {
  this.setMake = function (make) {
    this.make = make;
  }
  this.getMake = function () {
    return this.make;
  }

  this.setModel = function (model) {
    this.model = model;
  }
  this.getModel = function () {
    return this.model;
  }

  this.print = function () {
    console.log(this.make, this.model);
  }
}).call(Car.prototype); //Passing Car.prototype as "this"
//using Function.prototype.call, attaching required functions
//to Car's prototype


var skodaSuperb = new Car('Skoda', 'Superb');
skodaSuperb.print();

skodaSuperb.setModel('Octavia');
skodaSuperb.print();

//code 1.6

output

Skoda Superb
Skoda Octavia

//output 1.6

or

Option 2.1 (Non object Oriented way)

function.prototype.call can be used differently (not like option 2's Object Oriented Way)

'use strict'
function Car(make, model) {
  this.make = make;
  this.model = model;
}


function setMake(make) {
  this.make = make;
}
function getMake() {
  return this.make;
}

function setModel(model) {
  this.model = model;
}
function getModel() {
  return this.model;
}

function print() {
  console.log(this.make, this.model);
}


var skodaSuperb = new Car('Skoda', 'Superb');

//this is set to skodaSuperb for print function
print.call(skodaSuperb);

//this is set to skodaSuperb for setModel function
setModel.call(skodaSuperb, 'Octavia');
print.call(skodaSuperb);

// code 1.6.1

output

Skoda Superb
Skoda Octavia

//output 1.6

There are more ways to get the same thing done, and you'd be the judge of whats the best given the scenario.

What now?

This was my attempt to explain closure and how it affects almost every line of code that we write in javascript and how to take advantage of it and how to avoid it, how to create new execution scopes etc.

In coming articles we'll take a look into functional programming with javascript, then on basic building blocks of functional programming - call, bind and apply along with very handy higher order functions like map, reduce and filter.

Hope you guys enjoyed this article. Feel free to comment below, See you soon.

Cheers and Happy coding !!

Dave Amit

Dave Amit

Howdy folks! I am Dave Amit, an accidental programmer, father to a lab puppy, hubby to a beautiful wife, addicted to puzzles & a noob blogger. This is my effort to simplify odd codes from the wild.

Read More