Search code examples
programming-languagesclosures

Natural problems to solve using closures


I have read quite a few articles on closures, and, embarassingly enough, I still don't understand this concept! Articles explain how to create a closure with a few examples, but I don't see any point in paying much attention to them, as they largely look contrived examples. I am not saying all of them are contrived, just that the ones I found looked contrived, and I dint see how even after understanding them, I will be able to use them. So in order to understand closures, I am looking at a few real problems, that can be solved very naturally using closures.

For instance, a natural way to explain recursion to a person could be to explain the computation of n!. It is very natural to understand a problem like computing the factorial of a number using recursion. Similarly, it is almost a no-brainer to find an element in an unsorted array by reading each element, and comparing with the number in question. Also, at a different level, doing Object-oriented programming also makes sense.

So I am trying to find a number of problems that could be solved with or without closures, but using closures makes thinking about them and solving them easier. Also, there are two types to closures, where each call to a closure can create a copy of the environment variables, or reference the same variables. So what sort of problems can be solved more naturally in which of the closure implementations?


Solution

  • Alright, say you're generating a menu in, say, javascript.

    var menuItems = [
       { id: 1, text: 'Home' },
       { id: 2, text: 'About' },
       { id: 3, text: 'Contact' }
    ];
    

    And your creating them in a loop, like this:

    for(var i = 0; i < menuItems.length; i++) {
    
        var menuItem = menuItems[i];
    
        var a = document.createElement('a');
        a.href = '#';
        a.innerHTML = menuItem.text;
    
        // assign onclick listener
    
        myMenu.appendChild(a);
    
    }
    

    Now, for the onclick listener, you might attempt something like this:

    a.addEventListener('click', function() {
        alert( menuItem.id );
    }, false);
    

    But you'll find that this will have every link alert '3'. Because at the time of the click, your onclick code is executed, and the value of menuItem is evaluated to the last item, since that was the value it was last assigned, upon the last iteration of the for loop.

    Instead, what you can do is to create a new closure for each link, using the value of menuItem as it is at that point in execution

    a.addEventListener('click', (function(item) {
        return function() {
            alert( item.id );
        }
    })( menuItem ), false);
    

    So what's going on here? We're actually creating a function that accepts item and then immediately call that function, passing menuItem. So that 'wrapper' function is not what will be executed when you click the link. We're executing it immediately, and assigning the returned function as the click handler.

    What happens here is that, for each iteration, the function is called with a new value of menuItem, and a function is returned which has access to that value, which is effectively creating a new closure.

    Hope that cleared things up =)