简体   繁体   中英

Using closure for counting inside a function

I tried this and it always show 1 time, something's wrong, how to fix this?

    function myFunc() {

        var increment = (function() {
          var i = 0;
        
          return function() {
            i++;
            return i;
          };
        })();
        
        alert(`calling myFunc ${increment()} times`);

    }

Any time you call my func it's going to redefine the increment function, so you shouldn't expect it to ever say anything other than 1 . Your problem is that increment is being defined on every call to myFunc

What you want to do is this:

var i = 0;
function myFunc() {
    var increment = (function() {
        return function() {
            i++;
            return i;
        };
    })();
        
    alert(`calling myFunc ${increment()} times`);
}

So now i will keep its values between calls to myFunc . It'll have to be outside myFunc . Or you can move the whole function outside of myFunc .

var increment = (function() {
    var i = 0;
        
    return function() {
        i++;
        return i;
    };
})();
function myFunc() {
    alert(`calling myFunc ${increment()} times`);
}

Now this works:

console.log(increment()); // logs 1
console.log(increment()); // logs 2

The issue is that when a variable goes out of scope it is destroyed, the next time a value is called it will be recreated, and initialized at whatever value it starts as. As the variable i is scoped to inside the increment function, which is itself scoped to myFunc it means that when myFunc that closure is destroyed and will be created the next time the function is run.

An example that shows i hoisted to be in myFunc 's scope and the increment function running several times.

 function myFunc() { console.log('running myFunc'); var i = 0; console.log('assigning i to ' + i); function increment() { console.log('incrementing'); i++; }; increment(); increment(); console.log(`calling myFunc ${i} times`); } myFunc();

Notice that i now maintains its state across calls to increment . Now when we call myFunc multiple times, we see that i is destroyed, then a new variable is created when myFunc is run again.

 function myFunc() { console.log('running myFunc'); var i = 0; console.log('assigning i to ' + i); function increment() { console.log('incrementing'); i++; } increment(); increment(); console.log(`calling myFunc ${i} times`); } myFunc(); myFunc();

Now if we hoist i up to be above the scope of myFunc we'll see that it's value is kept within scope across calls to myFunc .

 var i = 0; console.log('assigning i to ' + i); function myFunc() { console.log('running myFunc'); function increment() { console.log('incrementing'); i++; } increment(); console.log(`calling myFunc ${i} times`); } myFunc(); myFunc();

Works for me.

 var increment = (function() { var i = 0; return function() { i++; return i; }; })(); console.log(increment()); console.log(increment()); console.log(increment());

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM