347

I'm trying my hardest to wrap my head around JavaScript closures.

I get that by returning an inner function, it will have access to any variable defined in its immediate parent.

Where would this be useful to me? Perhaps I haven't quite got my head around it yet. Most of the examples I have seen online don't provide any real world code, just vague examples.

Can someone show me a real world use of a closure?

Is this one, for example?

var warnUser = function (msg) {
    var calledCount = 0;
    return function() {
       calledCount++;
       alert(msg + '\nYou have been warned ' + calledCount + ' times.');
    };
};

var warnForTamper = warnUser('You can not tamper with our HTML.');
warnForTamper();
warnForTamper();
Ram
  • 3,092
  • 10
  • 40
  • 56
alex
  • 479,566
  • 201
  • 878
  • 984
  • 27
    +1 for trying your hardest :-) Closures can seem really daunting to begin with, I know they were for me. Once you get the hang of them, you'll instantly be a much better coder. – Andy E Apr 28 '10 at 09:54
  • 10
    I've just written a [blog post](http://skilldrick.co.uk/2010/11/a-brief-introduction-to-closures/) about closures in JavaScript that you may find helfpul. – Skilldrick Nov 23 '10 at 14:48
  • 1
    @Skilldrick. link is dead... and also I found this practical example to be very helpful. https://www.youtube.com/watch?v=w1s9PgtEoJs. – Abhi Jul 06 '16 at 17:45
  • Closures are also used for currying functions – Ghos3t Apr 05 '21 at 17:38

24 Answers24

344

Suppose, you want to count the number of times user clicked a button on a webpage.

For this, you are triggering a function on onclick event of button to update the count of the variable

<button onclick="updateClickCount()">click me</button>

Now there could be many approaches like:

  1. You could use a global variable, and a function to increase the counter:

     var counter = 0;
    
     function updateClickCount() {
         ++counter;
         // Do something with counter
     }
    

    But, the pitfall is that any script on the page can change the counter, without calling updateClickCount().


  1. Now, you might be thinking of declaring the variable inside the function:

     function updateClickCount() {
         var counter = 0;
         ++counter;
         // Do something with counter
     }
    

    But, hey! Every time updateClickCount() function is called, the counter is set to 1 again.


  1. Thinking about nested functions?

    Nested functions have access to the scope "above" them.

    In this example, the inner function updateClickCount() has access to the counter variable in the parent function countWrapper():

     function countWrapper() {
         var counter = 0;
         function updateClickCount() {
             ++counter;
             // Do something with counter
         }
         updateClickCount();
         return counter;
     }
    

    This could have solved the counter dilemma, if you could reach the updateClickCount() function from the outside and you also need to find a way to execute counter = 0 only once not everytime.


  1. Closure to the rescue! (self-invoking function):

     var updateClickCount = (function(){
         var counter = 0;
    
         return function(){
             ++counter;
             // Do something with counter
         }
     })();
    

    The self-invoking function only runs once. It sets the counter to zero (0), and returns a function expression.

    This way updateClickCount becomes a function. The "wonderful" part is that it can access the counter in the parent scope.

    This is called a JavaScript closure. It makes it possible for a function to have "private" variables.

    The counter is protected by the scope of the anonymous function, and can only be changed using the updateClickCount() function!

A more lively example on closures

<script>
var updateClickCount = (function(){
    var counter = 0;

    return function(){
        ++counter;
        document.getElementById("spnCount").innerHTML = counter;
    }
})();
</script>

<html>
<button onclick="updateClickCount()">click me</button>
<div> you've clicked
    <span id="spnCount"> 0 </span> times!
</div>
</html>

Reference: JavaScript Closures

Leonard
  • 2,978
  • 6
  • 21
  • 42
  • 84
    This is the first answer that made me say "Oh, *that's* why I would use closures!" –  Jun 07 '17 at 15:45
  • 25
    I just read the w3schools page on closures and then came here for more info. This is the same as the w3schools page: https://www.w3schools.com/js/js_function_closures.asp – tyelford Jun 14 '17 at 12:31
  • 4
    Good answer. Note though that a closure doesn't *need* to be a self-invoking function, but it *can* be. When a closure *is* self invoking (i.e. immediately called by adding () after the function), this means the return value is immediately calculated, rather than the *function* being returned and the return value being calculated *later* once the function is invoked. A closure can actually be any function within another function, and its key characteristic is that it has access to the scope of the parent function including it's variables and methods. – Chris Halcrow Feb 13 '18 at 10:28
  • updateClickCount() is still accessible in the console in developer tools, and the definition can be changed. For example, updateClickCount = function() {console.log('hacked');} – Pranjal Successena Jul 16 '18 at 16:39
  • same as the example discussed here https://www.w3schools.com/js/js_function_closures.asp – Nikhil Goyal Jan 18 '19 at 21:11
  • 1
    What's the validity of this answer with ES6? You can just use let and solve the problem. Just curious. – Esteban Vargas Apr 07 '20 at 22:03
  • 1
    this answer looks scraped from w3school too much. It even contains unrelated description. `The counter is protected by the scope of the anonymous function, and can only be changed using the add function`, while there is no add function in the example code. – DAMIEN JIANG May 26 '21 at 02:40
  • 1
    @EstebanVargas - I don't see how `let` can easily be used to solve the issue... Without wrapping everything in an IIFE, you still face the issue of not being able to initialise the `counter` variable, whilst protecting it from outside interference, and not resetting it to `1` everytime it's run. The ES6 easy solution would be to use `class`es, which can create private variables, and which behind the scenes uses closures to create the private `counter` variable, which can be seen in this fiddle - https://jsfiddle.net/gfy8n9um/ - By checking the console in a Chromium browser, within [[Scopes]]. – Jack_Hu Jul 23 '22 at 11:22
281

I've used closures to do things like:

a = (function () {
    var privatefunction = function () {
        alert('hello');
    }

    return {
        publicfunction : function () {
            privatefunction();
        }
    }
})();

As you can see there, a is now an object, with a method publicfunction ( a.publicfunction() ) which calls privatefunction, which only exists inside the closure. You can not call privatefunction directly (i.e. a.privatefunction() ), just publicfunction().

It's a minimal example, but maybe you can see uses to it? We used this to enforce public/private methods.

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
Francisco Soto
  • 10,277
  • 2
  • 37
  • 46
  • 34
    Ah, if this is a closure, then I have used closures without knowing it! I often put functions inside another like that, and then expose any I need public by returning an object literal like in your example. – alex Apr 28 '10 at 10:44
  • 1
    Yes, as you see, you keep the context of the function because the object you return references variables (and functions) inside it. So you've been using them, you just didn't know it. – Francisco Soto Apr 28 '10 at 10:54
  • 12
    Technically every function you make in Javascript on a browser is a closure because the window object is bound to it. – Adam Gent Apr 28 '10 at 12:17
  • 11
    I know this is an old question, but to me this still doesnt provide an adequate answer. Why not just call the function directly? Why do you need a private function? – qodeninja Feb 03 '14 at 19:17
  • 7
    Because even though the example has only a function, it could also have variables that are *not* accessible from the outside. Say: var obj = (function () { var value = 0; return { get: function () { return value; }, set: function (val) { value = val; } } })(); obj.set(20); obj.get(); => 20 etc. – Francisco Soto Feb 05 '14 at 18:17
  • I assume that a practical example would be to "cache" the result of a compicated computation. ie. if `privatefunction()` did some heavy calculation & wanted to cache the result of this computation in a local var called `myHeavyComptRes`. see an example I created http://jsbin.com/medevicuyajo/1/edit?js,console – Adriano Aug 22 '14 at 14:07
  • 1
    @alex here is an improvement of my previous comment's example http://jsbin.com/medevicuyajo/2/edit?js,console or its variation http://jsbin.com/medevicuyajo/3/edit?js,console , in the end closure seems to "only" be a work around for encapsulation as Javascript doesn't have any keyword ("private","public",...) providing such feature – Adriano Aug 22 '14 at 14:36
  • One possible interpretation of the upvotes to this the answer is that one of the most popular and practical uses of closures in JavaScript is to publish certain methods and not others (i.e. Hidding/Unhidding information in an object)? – gaboroncancio Oct 31 '14 at 13:54
  • 3
    Closures are incredibly useful in many situations but you have to be more adept in functional programming to get the most clever ways of using them. This is one simple way of using them that most people can use and understand right away. – Francisco Soto Nov 04 '14 at 19:31
  • 1
    How the typeof 'a' is object? – karthikaruna Apr 07 '17 at 12:48
73

The example you give is an excellent one. Closures are an abstraction mechanism that allow you to separate concerns very cleanly. Your example is a case of separating instrumentation (counting calls) from semantics (an error-reporting API). Other uses include:

  1. Passing parameterised behaviour into an algorithm (classic higher-order programming):

    function proximity_sort(arr, midpoint) {
        arr.sort(function(a, b) { a -= midpoint; b -= midpoint; return a*a - b*b; });
    }
    
  2. Simulating object oriented programming:

    function counter() {
        var a = 0;
        return {
            inc: function() { ++a; },
            dec: function() { --a; },
            get: function() { return a; },
            reset: function() { a = 0; }
        }
    }
    
  3. Implementing exotic flow control, such as jQuery's Event handling and AJAX APIs.

Marcelo Cantos
  • 181,030
  • 38
  • 327
  • 365
37

JavaScript closures can be used to implement throttle and debounce functionality in your application.

Throttling

Throttling puts a limit on as a maximum number of times a function can be called over time. As in "execute this function at most once every 100 milliseconds."

Code:

const throttle = (func, limit) => {
  let isThrottling
  return function() {
    const args = arguments
    const context = this
    if (!isThrottling) {
      func.apply(context, args)
      isThrottling = true
      setTimeout(() => isThrottling = false, limit)
    }
  }
}

Debouncing

Debouncing puts a limit on a function not be called again until a certain amount of time has passed without it being called. As in "execute this function only if 100 milliseconds have passed without it being called."

Code:

const debounce = (func, delay) => {
  let debouncing
  return function() {
    const context = this
    const args = arguments
    clearTimeout(debouncing)
    debouncing = setTimeout(() => func.apply(context, args), delay)
  }
}

As you can see closures helped in implementing two beautiful features which every web application should have to provide smooth UI experience functionality.

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
Mohd Asim Suhail
  • 2,176
  • 1
  • 16
  • 23
21

Yes, that is a good example of a useful closure. The call to warnUser creates the calledCount variable in its scope and returns an anonymous function which is stored in the warnForTamper variable. Because there is still a closure making use of the calledCount variable, it isn't deleted upon the function's exit, so each call to the warnForTamper() will increase the scoped variable and alert the value.

The most common issue I see on Stack Overflow is where someone wants to "delay" use of a variable that is increased upon each loop, but because the variable is scoped then each reference to the variable would be after the loop has ended, resulting in the end state of the variable:

for (var i = 0; i < someVar.length; i++)
    window.setTimeout(function () {
        alert("Value of i was "+i+" when this timer was set" )
    }, 10000);

This would result in every alert showing the same value of i, the value it was increased to when the loop ended. The solution is to create a new closure, a separate scope for the variable. This can be done using an instantly executed anonymous function, which receives the variable and stores its state as an argument:

for (var i = 0; i < someVar.length; i++)
    (function (i) {
        window.setTimeout(function () {
            alert("Value of i was " + i + " when this timer was set")
        }, 10000);
    })(i);
Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
Andy E
  • 338,112
  • 86
  • 474
  • 445
  • Interesting -1, I guess this is not "a practical use for a closure in javascript"? – Andy E Apr 28 '10 at 11:25
  • 1
    I found some use in reading it so I awarded a +1 before the downvote. – alex Apr 28 '10 at 11:49
  • 1
    @alex: thanks, I did notice the upvote. I've almost gotten used to anonymous downvotes here at SO. It only annoys me because I'd really like to know if I've said something inaccurate or wrong, and they tend to make you think you've just been downvoted by some other answerer who wants better visibility for their own answer. Fortunately, I'm not the vengeful type ;-) – Andy E Apr 28 '10 at 14:30
  • @Any E's head Well if anyone can let Andy or I know if there is any misleading information, we can amend and make SO a better place :) – alex Apr 28 '10 at 14:34
  • 1
    I think this is more a work around for JavaScripts broken block scope. You should just be able to add var j = i; before the first setTimeout and get the alert to use that j. Another work around is to use 'with' like so: for (var i = 0; i < someVar.length; i++){ with({i:i}){window.setTimeout(function () {alert("Value of i was "+i+" when this timer was set" )}, 100);}} – davidbuttar Sep 03 '13 at 17:17
  • @AndyE old answer I know, but I'm trying to understand this in terms of the definition of closure: `"To use a closure, simply define a function inside another function and expose it. To expose a function, return it or pass it to another function." ... "The inner function will have access to the variables in the outer function scope, even after the outer function has returned."` - Where is the "passing to another function or returning" portion happening? My guess is that the `IIFE` is able to remember the outer `i` for loop value at each iteration because the `IIFE` is passed to the window? – user3871 Jul 17 '17 at 06:11
  • @AndyE ...where the `i` in the outer `for-loop` is bound to the function's scope that contains the `for-loop`. – user3871 Jul 17 '17 at 06:15
  • The funny thing is that your first code block is *already* using a closure: the callback function you're declaring in setTimeout. It has a reference to i, which is why when the callbacks are executed they all show the same value of i (they are all referencing the same variable). – antoine Jul 07 '18 at 21:42
  • @antoine I don't see what's funny about that :-P (or how it's relevant to the question or answer) – Andy E Jul 13 '18 at 11:01
  • 1
    @AndyE Funny might not be the right word. I just noticed that often people use self-invoking functions to explain closures, like many answers on this page. But the callback function in the setTimeout is also a closure; it might be considered "a practical use" since you could access some other local variables from the callback. When I was learning about closures, realising this was useful to me - that closures are everywhere, not just in arcade JavaScript patterns. – antoine Jul 16 '18 at 15:32
  • @antoine yeah, I guess people just find it easier to use the self-invoking function to explain, but you're right, it's odd that most people skirt around what a closure really is. I've interviewed potential recruits where I've asked them to explain a closure and sometimes they just awkwardly say 'it's a function that calls itself' – Andy E Jul 18 '18 at 10:22
19

In the JavaScript (or any ECMAScript) language, in particular, closures are useful in hiding the implementation of functionality while still revealing the interface.

For example, imagine you are writing a class of date utility methods and you want to allow users to look up weekday names by index, but you don't want them to be able to modify the array of names you use under the hood.

var dateUtil = {
  weekdayShort: (function() {
    var days = ['Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat', 'Sun'];
    return function(x) {
      if ((x != parseInt(x)) || (x < 1) || (x > 7)) {
        throw new Error("invalid weekday number");
      }
      return days[x - 1];
    };
  }())
};

Note that the days array could simply be stored as a property of the dateUtil object, but then it would be visible to users of the script and they could even change it if they wanted, without even needing your source code. However, since it's enclosed by the anonymous function which returns the date lookup function it is only accessible by the lookup function so it is now tamperproof.

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
maerics
  • 151,642
  • 46
  • 269
  • 291
  • 2
    This might sound dumb, but couldn't they just open up the JavaScript file itself and see your implementation? – itsmichaelwang Dec 15 '14 at 06:49
  • 1
    @Zapurdead: yes, they could of course *see* the implementation but they could not *change* the implementation (accidentally or intentionally) without directly modifying your source code. I suppose you could compare it to protected members in Java. – maerics Dec 15 '14 at 15:36
  • This is why closure exists as @maerics described here above ... ..closures are useful in hiding the implementation of functionality while still revealing the interface... – MasterOfTheHouse Dec 20 '21 at 17:55
8

There is a section on Practical Closures at the Mozilla Developer Network.

Dan Dascalescu
  • 143,271
  • 52
  • 317
  • 404
alex
  • 479,566
  • 201
  • 878
  • 984
  • 1
    Looking through this, I don't see how it is "practical" as if I remove the whole `return function ()...` the code still works fine. The closure is not nessecary – James Parsons Aug 15 '15 at 02:47
  • @James_Parsons You couldn't then assign them to event handlers like they have done in the example then. – alex Aug 16 '15 at 23:57
  • closures are useful in hiding the implementation of functionality while still revealing the interface. It helps you create private members that can only be accessible changed and modified by using the closure.. – MasterOfTheHouse Dec 20 '21 at 17:56
7

If you're comfortable with the concept of instantiating a class in the object-oriented sense (i.e. to create an object of that class) then you're close to understanding closures.

Think of it this way: when you instantiate two Person objects you know that the class member variable "Name" is not shared between instances; each object has its own 'copy'. Similarly, when you create a closure, the free variable ('calledCount' in your example above) is bound to the 'instance' of the function.

I think your conceptual leap is slightly hampered by the fact that every function/closure returned by the warnUser function (aside: that's a higher-order function) closure binds 'calledCount' with the same initial value (0), whereas often when creating closures it is more useful to pass different initializers into the higher-order function, much like passing different values to the constructor of a class.

So, suppose when 'calledCount' reaches a certain value you want to end the user's session; you might want different values for that depending on whether the request comes in from the local network or the big bad internet (yes, it's a contrived example). To achieve this, you could pass different initial values for calledCount into warnUser (i.e. -3, or 0?).

Part of the problem with the literature is the nomenclature used to describe them ("lexical scope", "free variables"). Don't let it fool you, closures are more simple than would appear... prima facie ;-)

EdwardG
  • 2,029
  • 2
  • 15
  • 15
7

Here, I have a greeting that I want to say several times. If I create a closure, I can simply call that function to record the greeting. If I don't create the closure, I have to pass my name in every single time.

Without a closure (https://jsfiddle.net/lukeschlangen/pw61qrow/3/):

function greeting(firstName, lastName) {
  var message = "Hello " + firstName + " " + lastName + "!";
  console.log(message);
}

greeting("Billy", "Bob");
greeting("Billy", "Bob");
greeting("Billy", "Bob");
greeting("Luke", "Schlangen");
greeting("Luke", "Schlangen");
greeting("Luke", "Schlangen");

With a closure (https://jsfiddle.net/lukeschlangen/Lb5cfve9/3/):

function greeting(firstName, lastName) {
  var message = "Hello " + firstName + " " + lastName + "!";

  return function() {
    console.log(message);
  }
}

var greetingBilly = greeting("Billy", "Bob");
var greetingLuke = greeting("Luke", "Schlangen");

greetingBilly();
greetingBilly();
greetingBilly();
greetingLuke();
greetingLuke();
greetingLuke();
Luke Schlangen
  • 3,722
  • 4
  • 34
  • 69
  • 1
    I am not sure but still without a closure u can call as var grretBilly= greeting("Billy", "Bob"); and call grretBilly(); It stilll would do the same ?? although u create closure or not thats a different issue but passing of name each time is not a issue here. – user2906608 Dec 03 '18 at 06:15
5

Another common use for closures is to bind this in a method to a specific object, allowing it to be called elsewhere (such as as an event handler).

function bind(obj, method) {
    if (typeof method == 'string') {
        method = obj[method];
    }
    return function () {
        method.apply(obj, arguments);
    }
}
...
document.body.addEventListener('mousemove', bind(watcher, 'follow'), true);

Whenever a mousemove event fires, watcher.follow(evt) is called.

Closures are also an essential part of higher-order functions, allowing the very common pattern of rewriting multiple similar functions as a single higher order function by parameterizing the dissimilar portions. As an abstract example,

foo_a = function (...) {A a B}
foo_b = function (...) {A b B}
foo_c = function (...) {A c B}

becomes

fooer = function (x) {
    return function (...) {A x B}
}

where A and B aren't syntactical units but source code strings (not string literals).

See "Streamlining my javascript with a function" for a concrete example.

Community
  • 1
  • 1
outis
  • 75,655
  • 22
  • 151
  • 221
5

Here I have one simple example of the closure concept which we can use for in our E-commerce site or many others as well.

I am adding my JSFiddle link with the example. It contains a small product list of three items and one cart counter.

JSFiddle

// Counter closure implemented function;
var CartCouter = function(){
  var counter = 0;

  function changeCounter(val){
      counter += val
  }

  return {
      increment: function(){
        changeCounter(1);
    },
    decrement: function(){
      changeCounter(-1);
    },
    value: function(){
      return counter;
    }
  }
}

var cartCount = CartCouter();

function updateCart() {
  document.getElementById('cartcount').innerHTML = cartCount.value();
}

var productlist = document.getElementsByClassName('item');
for(var i = 0; i< productlist.length; i++){
  productlist[i].addEventListener('click', function(){
    if(this.className.indexOf('selected') < 0){
      this.className += " selected";
      cartCount.increment();
      updateCart();
    }
    else{
      this.className = this.className.replace("selected", "");
      cartCount.decrement();
      updateCart();
    }
  })
}
.productslist{
  padding: 10px;
}
ul li{
  display: inline-block;
  padding: 5px;
  border: 1px solid #DDD;
  text-align: center;
  width: 25%;
  cursor: pointer;
}
.selected{
  background-color: #7CFEF0;
  color: #333;
}
.cartdiv{
  position: relative;
  float: right;
  padding: 5px;
  box-sizing: border-box;
  border: 1px solid #F1F1F1;
}
<div>
    <h3>
        Practical use of a JavaScript closure concept/private variable.
    </h3>

    <div class="cartdiv">
        <span id="cartcount">0</span>
    </div>

    <div class="productslist">
        <ul>
            <li class="item">Product 1</li>
            <li class="item">Product 2</li>
            <li class="item">Product 3</li>
        </ul>
    </div>
</div>
Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
Abhilash KK
  • 448
  • 5
  • 19
4

Use of Closures:

Closures are one of the most powerful features of JavaScript. JavaScript allows for the nesting of functions and grants the inner function full access to all the variables and functions defined inside the outer function (and all other variables and functions that the outer function has access to). However, the outer function does not have access to the variables and functions defined inside the inner function.

This provides a sort of security for the variables of the inner function. Also, since the inner function has access to the scope of the outer function, the variables and functions defined in the outer function will live longer than the outer function itself, if the inner function manages to survive beyond the life of the outer function. A closure is created when the inner function is somehow made available to any scope outside the outer function.

Example:

<script>
var createPet = function(name) {
  var sex;
  
  return {
    setName: function(newName) {
      name = newName;
    },
    
    getName: function() {
      return name;
    },
    
    getSex: function() {
      return sex;
    },
    
    setSex: function(newSex) {
      if(typeof newSex == "string" && (newSex.toLowerCase() == "male" || newSex.toLowerCase() == "female")) {
        sex = newSex;
      }
    }
  }
}

var pet = createPet("Vivie");
console.log(pet.getName());                  // Vivie

console.log(pet.setName("Oliver"));   
console.log(pet.setSex("male"));
console.log(pet.getSex());                   // male
console.log(pet.getName());                  // Oliver
</script>

In the code above, the name variable of the outer function is accessible to the inner functions, and there is no other way to access the inner variables except through the inner functions. The inner variables of the inner function act as safe stores for the inner functions. They hold "persistent", yet secure, data for the inner functions to work with. The functions do not even have to be assigned to a variable, or have a name. read here for detail.

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
Sunny S.M
  • 5,768
  • 1
  • 38
  • 38
2

I like Mozilla's function factory example.

function makeAdder(x) {

    return function(y) {
        return x + y;
    };
}

var addFive = makeAdder(5);

console.assert(addFive(2) === 7);
console.assert(addFive(-5) === 0);
Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
Tom
  • 419
  • 4
  • 5
  • 16
    This is the type of example that doesn't help people understand closures or what good they're for, in my opinion. How many times have you ever written a closure to return a function to add numbers, other than as an example? – Mohamad Nov 02 '15 at 01:14
2

The JavaScript module pattern uses closures. Its nice pattern allows you to have something alike "public" and "private" variables.

var myNamespace = (function () {

  var myPrivateVar, myPrivateMethod;

  // A private counter variable
  myPrivateVar = 0;

  // A private function which logs any arguments
  myPrivateMethod = function(foo) {
      console.log(foo);
  };

  return {

    // A public variable
    myPublicVar: "foo",

    // A public function utilizing privates
    myPublicFunction: function(bar) {

      // Increment our private counter
      myPrivateVar++;

      // Call our private method using bar
      myPrivateMethod(bar);
    }
  };

})();
Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
2

This thread has helped me immensely in gaining a better understanding of how closures work.

I've since done some experimentation of my own and came up with this fairly simple code which may help some other people see how closures can be used in a practical way and how to use the closure at different levels to maintain variables similar to static and/or global variables without risk of them getting overwritten or confused with global variables.

This keeps track of button clicks, both at a local level for each individual button and a global level, counting every button click, contributing towards a single figure. Note I haven't used any global variables to do this, which is kind of the point of the exercise - having a handler that can be applied to any button that also contributes to something globally.

Please experts, do let me know if I've committed any bad practices here! I'm still learning this stuff myself.

<!doctype html>
<html>

<head>
    <meta charset="utf-8">
    <title>Closures on button presses</title>

    <script type="text/javascript">

        window.addEventListener("load" , function () {
            /*
                Grab the function from the first closure,
                and assign to a temporary variable
                this will set the totalButtonCount variable
                that is used to count the total of all button clicks
            */
            var buttonHandler = buttonsCount();

            /*
                Using the result from the first closure (a function is returned)
                assign and run the sub closure that carries the
                individual variable for button count and assign to the click handlers
            */
            document.getElementById("button1").addEventListener("click" , buttonHandler() );
            document.getElementById("button2").addEventListener("click" , buttonHandler() );
            document.getElementById("button3").addEventListener("click" , buttonHandler() );

            // Now that buttonHandler has served its purpose it can be deleted if needs be
            buttonHandler = null;
        });


        function buttonsCount() {
            /*
                First closure level
                - totalButtonCount acts as a sort of global counter to count any button presses
            */
            var totalButtonCount = 0;

            return  function () {
                // Second closure level
                var myButtonCount = 0;

                return function (event) {
                    // Actual function that is called on the button click
                    event.preventDefault();
                    /*
                       Increment the button counts.
                       myButtonCount only exists in the scope that is
                       applied to each event handler and therefore acts
                       to count each button individually, whereas because
                       of the first closure totalButtonCount exists at
                       the scope just outside, it maintains a sort
                       of static or global variable state
                    */

                    totalButtonCount++;
                    myButtonCount++;

                    /*
                        Do something with the values ... fairly pointless
                        but it shows that each button contributes to both
                        its own variable and the outer variable in the
                        first closure
                    */
                    console.log("Total button clicks: "+totalButtonCount);
                    console.log("This button count: "+myButtonCount);
                }
            }
        }
    </script>
</head>

<body>
    <a href="#" id="button1">Button 1</a>
    <a href="#" id="button2">Button 2</a>
    <a href="#" id="button3">Button 3</a>
</body>

</html>
Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
Darren Crabb
  • 570
  • 2
  • 10
2

Explaining the practical use for a closure in JavaScript

When we create a function inside another function, we are creating a closure. Closures are powerful because they are capable of reading and manipulating the data of its outer functions. Whenever a function is invoked, a new scope is created for that call. The local variable declared inside the function belong to that scope and they can only be accessed from that function. When the function has finished the execution, the scope is usually destroyed.

A simple example of such function is this:

function buildName(name) {
    const greeting = "Hello, " + name;
    return greeting;
}

In above example, the function buildName() declares a local variable greeting and returns it. Every function call creates a new scope with a new local variable. After the function is done executing, we have no way to refer to that scope again, so it’s garbage collected.

But how about when we have a link to that scope?

Let’s look at the next function:

function buildName(name) {
    const greeting = "Hello, " + name + " Welcome ";
    const sayName = function() {
        console.log(greeting);
    };
    return sayName;
}

const sayMyName = buildName("Mandeep");
sayMyName();  // Hello, Mandeep Welcome

The function sayName() from this example is a closure. The sayName() function has its own local scope (with variable welcome) and has also access to the outer (enclosing) function’s scope. In this case, the variable greeting from buildName().

After the execution of buildName is done, the scope is not destroyed in this case. The sayMyName() function still has access to it, so it won’t be garbage collected. However, there is no other way of accessing data from the outer scope except the closure. The closure serves as the gateway between the global context and the outer scope.

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
2

There are various use cases of closures.Here, I am going to explain most important usage of Closure concept.

  • Closure can be used to create private methods and variables just like an object-oriented language like java, c++ and so on. Once you implemented private methods and variables, your variables defined inside a function won't be accessible by window object. This helps in data hiding and data security.
const privateClass = () => {
  let name = "sundar";
  function setName(changeName) {
    name = changeName;
  }
  function getName() {
    return name;
  }
  return {
    setName: setName,
    getName: getName,
  };
};

let javaLikeObject = privateClass(); \\ similar to new Class() in OOPS.

console.log(javaLikeObject.getName()); \\this will give sundar
javaLikeObject.setName("suresh");
console.log(javaLikeObject.getName()); \\this will give suresh

  • Another real-life example of closure :

Create index.html:

<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>Program with Javascript</title>
  </head>
  <body>
    <p id="first"></p>
    <p id="second"></p>
    <button onclick="applyingConcepts()">Click</button>
    <script src="./index.js"></script>
  </body>
</html>

2)In index.js:

  let count = 0;
  return () => {
    document.getElementById("first").innerHTML = count++;
  };
})();

  • In this example, when you click a button, then your count will be updated on p#id. Note: You might be wondering what's special in this code. When you inspect, you will notice that you can't change the value of count using the window object. This means you have declared private variable count so this prevents your states from being spoiled by the client.
Sundar Gautam
  • 445
  • 1
  • 6
  • 10
1

I wrote an article a while back about how closures can be used to simplify event-handling code. It compares ASP.NET event handling to client-side jQuery.

http://www.hackification.com/2009/02/20/closures-simplify-event-handling-code/

stusmith
  • 14,003
  • 7
  • 56
  • 89
0

Closures are a useful way to create , a sequence incremented on-demand:

    var foobar = function(i){var count = count || i; return function(){return ++count;}}

    baz = foobar(1);
    console.log("first call: " + baz()); //2
    console.log("second call: " + baz()); //3

The differences are summarized as follows:

Anonymous functions                                    Defined functions

Cannot be used as a method                             Can be used as a method of an object

Exists only in the scope in which it is defined        Exists within the object it is defined in

Can only be called in the scope in which it is defined Can be called at any point in the code

Can be reassigned a new value or deleted               Cannot be deleted or changed

References

Paul Sweatte
  • 24,148
  • 7
  • 127
  • 265
0

Reference: Practical usage of closures

In practice, closures may create elegant designs, allowing customization of various calculations, deferred calls, callbacks, creating encapsulated scope, etc.

An example is the sort method of arrays which accepts the sort condition function as an argument:

[1, 2, 3].sort(function (a, b) {
    ... // Sort conditions
});

Mapping functionals as the map method of arrays which maps a new array by the condition of the functional argument:

[1, 2, 3].map(function (element) {
    return element * 2;
}); // [2, 4, 6]

Often it is convenient to implement search functions with using functional arguments defining almost unlimited conditions for search:

someCollection.find(function (element) {
    return element.someProperty == 'searchCondition';
});

Also, we may note applying functionals as, for example, a forEach method which applies a function to an array of elements:

[1, 2, 3].forEach(function (element) {
    if (element % 2 != 0) {
        alert(element);
    }
}); // 1, 3

A function is applied to arguments (to a list of arguments — in apply, and to positioned arguments — in call):

(function () {
    alert([].join.call(arguments, ';')); // 1;2;3
}).apply(this, [1, 2, 3]);

Deferred calls:

var a = 10;
setTimeout(function () {
    alert(a); // 10, after one second
}, 1000);

Callback functions:

var x = 10;
// Only for example
xmlHttpRequestObject.onreadystatechange = function () {
    // Callback, which will be called deferral ,
    // when data will be ready;
    // variable "x" here is available,
    // regardless that context in which,
    // it was created already finished
    alert(x); // 10
};

Creation of an encapsulated scope for the purpose of hiding auxiliary objects:

var foo = {};
(function (object) {
    var x = 10;
    object.getX = function _getX() {
        return x;
    };
})(foo);

alert(foo.getX()); // Get closured "x" – 10
Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
Damodaran
  • 10,882
  • 10
  • 60
  • 81
0

Much of the code we write in front-end JavaScript is event-based — we define some behavior, then attach it to an event that is triggered by the user (such as a click or a keypress). Our code is generally attached as a callback: a single function which is executed in response to the event. size12, size14, and size16 are now functions which will resize the body text to 12, 14, and 16 pixels, respectively. We can attach them to buttons (in this case links) as follows:

function makeSizer(size) {
    return function() {
    document.body.style.fontSize = size + 'px';
    };
}

var size12 = makeSizer(12);
var size14 = makeSizer(14);
var size16 = makeSizer(16);

document.getElementById('size-12').onclick = size12;
document.getElementById('size-14').onclick = size14;
document.getElementById('size-16').onclick = size16;

Fiddle

Muhammad Usman
  • 863
  • 1
  • 11
  • 18
  • While this code may answer the question, providing additional context regarding how and/or why it solves the problem would improve the answer's long-term value. – Donald Duck Mar 03 '17 at 12:04
  • 1
    this example, it seems to me, could be implemented without closure via a standard function. I'm trying to find an example of something that COULDN'T be implemented without closure – Zach Smith May 05 '17 at 16:26
0

In the given sample, the value of the enclosed variable 'counter' is protected and can be altered only using the given functions (increment, decrement). Because it is in a closure,

var MyCounter = function (){
    var counter = 0;
    return {
        increment:function () {return counter += 1;},
        decrement:function () {return counter -= 1;},
        get:function () {return counter;}
    };
};

var x = MyCounter();
// Or
var y = MyCounter();

alert(x.get()); // 0
alert(x.increment()); // 1
alert(x.increment()); // 2

alert(y.increment()); // 1
alert(x.get()); // x is still 2
Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
ShAkKiR
  • 863
  • 9
  • 20
0

I'm trying to learn closures and I think the example that I have created is a practical use case. You can run a snippet and see the result in the console.

We have two separate users who have separate data. Each of them can see the actual state and update it.

function createUserWarningData(user) {
  const data = {
    name: user,
    numberOfWarnings: 0,
  };

  function addWarning() {
    data.numberOfWarnings = data.numberOfWarnings + 1;
  }

  function getUserData() {
    console.log(data);
    return data;
  }

  return {
    getUserData: getUserData,
    addWarning: addWarning,
  };
}

const user1 = createUserWarningData("Thomas");
const user2 = createUserWarningData("Alex");

//USER 1
user1.getUserData(); // Returning data user object
user1.addWarning(); // Add one warning to specific user
user1.getUserData(); // Returning data user object

//USER2
user2.getUserData(); // Returning data user object
user2.addWarning(); // Add one warning to specific user
user2.addWarning(); // Add one warning to specific user
user2.getUserData(); // Returning data user object
Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
0

Everyone has explained the practical use cases of closure: the definition and a couple of examples.

I want to contribute a list of use cases of Closures:

  • suppose you want to count no of times a button is clicked; Closure is the best choice.
  • Throttling and Debounce
  • Currying
  • Memorize
  • Maintaining state in the async world
  • Functions like once
  • setTimeouts
  • Iterators
Balram Singh
  • 1,576
  • 19
  • 30