What are the use of closure functions?

I understand the closure functions, but I cannot guess what kind of thing they are used for, where can we use it except a counter that is not intended to be accessed from the outside?

So, in my opinion, they are great for functions that are single purpose, like responding to a click event from a button. They are great for UI functions and for things you don’t want to re-use. I hope that helps.

All functions in JavaScript are closures, practically there is no distinction, it’s a core part of how JS works.

But as for using closures explicitly, as the first example:

JS, when it executes in a browser, is single-threaded (and code for NodeJS is written as if it were single-threaded). It means you can only do one thing at a time, and those things happen in the order they are written in the code. You cannot (with some exceptions) tell part of your program to go and do one thing at the same time as the rest of your program is doing another.

This could be a problem when you want to do {something} when {something else that might take time} happens. Like making an HTTP request: you don’t want the program to lock up while it waits. What you want is to make a request, let the rest of the program carry on, then run a function (do {something}) when the request is complete. And you want that function to “remember” the original context it was called in, the details of that request, or event, or whatever.

makeARequest.then((data) => console.log(data));

What is data there? It’s just an argument to that callback function, how does it get populated? If I write

let data = "foo";

makeARequest.then((data) => console.log(data));

how come the callback function doesn’t use the value “foo” instead of whatever comes back from the request? And the callback function only executes when that request completes, so how does the callback function keep hold of the information from the original request (the callback function could be fired long after the original request was made)?


As a second example, say I map over an array of numbers, multiplying each one by 2:

[1,2,3,4].map(num => num * 2);

Why is num going to be each of those values in turn? If I do this:

num = 10;
[1,2,3,4].map(num => num * 2);

Why is the result [2,4,6,8] rather than [20,20,20,20]? How does the function (num) => num * 2 “know” to use the value you want for num?

This is all to do with scope, ie the rules around how and where variables are bound to values. And the technique used to implement scope in JS is closure. In JS, you can pass around functions just the same as any other value (you can pass them as arguments to other functions, you can return them from functions, you can assign them to variables). Without closures, you would not really be able to do that easily. There are other ways that it can be done, in a limited manner – there are languages that don’t support closures and they work fine, but in general most languages do support them. And for languages like JavaScript, they are central to how programs are normally written.


Closures are also an alternative to objects (and vice versa). So in a simplified example from an application I work on, I have to format distances in the UI. The distances are stored in metres, but they need to be formatted as either km or miles depending on what the user’s preference is. So I could use an object:

class Distance {
  #unitPreference = "km";

  constructor (initialUnitPref = "km") {
    this.#unitPref = initialUnitPref;
  }

  setUnitPreference(pref) {
    this.#unitPref = pref;
  }

  format(dist) {
    switch (this.#unitPref) {
      case "km": return `${metresToKm(dist)} km`;
      case "mi": return `${metresToMi(dist)} mi`;
    }
  }
}

Then at the top of my app, I keep the object around something like:

distanceFormatter = new Distance();

// which I can use like:
distanceFormatter.format(12345);

// And when a user wants to update the preference:
distanceFormatter.setUnitPreference("mi");

However, that is a pain due to the library I use for the UI (React). The actual instance of Distance only mutates its state, it’s still the same object. So when a user updates their preferences from km to miles or vice versa, the actual formatter functions wouldn’t rerun automatically – the formatting in the UI would still be whatever the original preference was. I’d need to figure out a way to force them to rerun. Not much of an issue, but it’s easier if I don’t use an object, and instead use a function that relies on how closure works.

export function distance(unitPreference = "km") {
  return function (distanceInMetres) {
    switch (unitPreference) {
      case "km":
        return `${metresToKm(distanceInMetres))} km`;
      case "mi":
        return `${metresToMiles(distanceInMetre)} mi`;
    }
  };
}

So

distanceFormatter = distance();

// to format a distance in metres:
distanceFormatter(12345);

// And when I want to update the preferences, I just
// run the `distance` function again:
distanceFormatter = distance("mi");

When the distance function is rerun, all the actual calls to distanceFormatter also get rerun with the new version of the function with the new preferences.

3 Likes

This topic was automatically closed 182 days after the last reply. New replies are no longer allowed.