I was explaining javascript closure to a friend like this:
function outer() {
var count = 0;
return (function(){
count++;
console.log(count);
})();
}
I was trying to show him that how does this 'count' variable is stored when the outer function is executed.
So I tried doing this in the javascript console and wanted to show him that when you do this in the console
outer(); // prints out 1
outer(); // calling again prints 2
outer(); // prints out 3
but actually this happened
outer(); // printed 1
outer(); // printed 1 again
outer(); // again 1
I don't understand whats going wrong here. Can someone guide me.
3 Answers 3
Thanks to @elclanrs. This is the working code.
function outer() {
var count = 0;
return (function(){
count++;
console.log(count);
});
}
Now when i call this function and store it in a variable
var myouter = outer();
myouter();
// 1
// undefined
myouter();
// 2
// undefined
myouter();
// 3
// undefined
Comments
It is because your count is declared inside the function, so it is "private" to the function scope, so every time your function is called, the variable count will be created and initialized to 0 then your inner function, aka, closure increments it, that is why it prints 1, then when your closure returns, your count variable is garbage-collected because its scope ends there -- within the matching curly braces, try moving count to the outermost outside any function, then you will get what you want, then your count will become a global variable which is not good in production code because you dont want to taint your global pool, and create memory leak problem. Closures are basically just inner functions like in Java.
2 Comments
count private to inner function and still show him the example in this way only. Do you have a way to do that? I wanted to show him how closures is used to keep variables private to themselves. So your answer doesn't applies in this case.count is scoped to the function, however you can use setTimeout() to achieve what you want.You set count=0 every time you call outer(). If you want count to be private, meaning outside global scope, then I would use a module pattern like this:
var counter = (function(c){
var count = 0;
c.outer = function(){
count++;
console.log(count);
};
return c;
}({} || counter))
counter.outer();
or you can simply have outer() return a function:
function outer() {
var count = 0;
return function(){
count++;
console.log(count);
};
}
var myo = outer();
myo();
myo();
myo();
var myouter = outer(); myouter(); myouter(); myouter()myouter();throws an error "TypeError: undefined is not a function"outeris not returning a function, it is returningundefined. Return a function, but don't execute it and it should work.