Reputation: 65
var add = (function () {
var counter = 0;
return function () {
var reset = function() {
counter = 0;
}
return counter += 1;
}
})();
This is a self-invoking function that creates a "private" variable. How would I create a function reset
that will reset the counter to 0? I've tried declaring the function inside the closure, but when I call it using add.reset(), it tells me this method is undefined.
Upvotes: 2
Views: 2963
Reputation: 20359
If you would like to keep the privacy of your current count, here is an answer that uses an object:
function counter() {
var count = 0;
this.reset = function() {
count = 0;
return count;
};
this.add = function() {
return ++count;
};
}
Then for instance:
var counter1 = new counter();
counter1.add();
console.log(counter1.add());
console.log(counter1.reset());
Upvotes: 0
Reputation: 1167
If you want to explicitly keep the counter declared inside the closure, you need to declare reset (even if you don't give it a value) outside the closure. To use your code, it would look like this:
var reset;
var add = (function () {
var counter = 0;
return function () {
reset = function() {
counter = 0;
}
return counter += 1;
}
})();
Now reset is outside the scope of the add function, so it keeps the value assigned within it!
To be fair, though, there's no reason to assign reset every time you can the result of add... It might be better to do something like:
var reset;
var add = (function () {
var counter = 0;
reset = function() {
counter = 0;
}
return function () {
return counter += 1;
}
})();
Or better still, if you want add.reset()
to work:
var counter = function () {
var counter = 0;
this.reset = function() {
counter = 0;
}
this.add = function () {
return counter += 1;
}
};
var add = new counter();
Then add is a full object, which more or less sounds like what you want.
Or if you want to stick with the self invoking function:
var add = (function () {
var counter = 0;
return function () {
this.reset = function() {
counter = 0;
}
return counter += 1;
}
})();
Would probably work. It would be a slightly unusual paradigm from what I've seen though...
Upvotes: 1
Reputation: 20359
I would recommend that instead of trying to put the function inside your closure, you put your variable outside your closure, like this:
var counter = 0;
var add = function() {
return counter += 1;
};
var reset = function() {
counter = 0;
};
That way the variable has proper scope for what you are trying to accomplish with it.
Upvotes: 3
Reputation: 147363
You should return the reset function as a method of the object returned by the IIFE. That object needs to be the add function, so put the reset method on it. Just do it like you would in a global context, but inside a closure and return the add function, e.g.:
var add = (function(){
var counter = 0;
function add(n) {
counter += n || 0;
return counter;
}
add.reset = function(){
counter = 0;
return counter;
}
return add;
}())
console.log(add(1)) // 1
console.log(add(4)) // 5
console.log(add.reset()); // 0
However, it would make more sense (to me) to have a counter object that has add and reset methods.
Upvotes: 5