What is a practical use for a closure in JavaScript?

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();

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 (ie a.privatefunction() ), just publicfunction() .

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


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() .


2) 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.


3) 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.


4) 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 add function!

More lively example on Closure:

  <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>

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:

  • 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; });
    }
    
  • Simulating object oriented programming:

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

  • 链接地址: http://www.djcxy.com/p/152.html

    上一篇: 循环内的JavaScript闭包 - 一个简单实用的例子

    下一篇: JavaScript中关闭的实际用法是什么?