Reputation: 45
var addCount;
function s1() {
var count = 0;
addCount = function() {
count++;
};
function s12() {
console.log(count)
}
return s12
}
var result1 = s1();
var result2 = s1();
addCount();
result1(); // count = 0;
result2(); // count = 1;
In the picture I marked the puzzled place Then, the next step will be shown in this way This is where I am really puzzled
Upvotes: 4
Views: 129
Reputation: 65808
Because result
is a function that is declared as being the result of calling the s1
function. Calling s1
returns the s12
function and that function uses a variable called count
which is declared at a higher level (scope) than itself (this is called a "free variable").
When a free variable is used inside of a function that has a lifetime that is longer than the function where the free variable was declared, a "closure" is created around that free variable and it stays in scope even after the function it was declared in terminates.
When you call result
the first time, count
increases by one and that value stays in memory so that when you call it a second time, you are working with the last value.
Upvotes: 5
Reputation: 45659
To understand this behavior, you need to really understand what closures do. The short (but probably confusing if you aren't really in tune with closures) answer is this:
Each invocation of s1
does the following:
A) Create a variable named count and initialize it to 0
This seems straightforward enough...
B) Create a function that increments the variable from (A), and set the addCount
variable to point to it
Some important details are hidden here. The variable this function will update is the one created in step (A) of the same invocation of s1
. This is a consequence of the closure mechanism.
Of course when the 2nd invocation of s1
reaches this step, it overwrites the value of addEvent
, replacing the function that increments the count
created by the prior invocation of s1
with a new function that increments the count
created by this current invocation of s1
.
C) Create and return a function that logs the value of the variable created in (A)
As with (B), this function too sees the variable created by step A of the current invocation of s1
.
So what does that mean?
Well, you call s1
once and it creates a variable, with value 0, and returns a function that logs that variable (which function you've stored as result1
).
As a side effect, that call had set addCount
to a function that would change the value of the variable logged by result1
if you called it... but you don't call it.
Instead you call s1
again, which replaces addCount
with a new function that updates a new variable (also initialized to 0). It returns a function that logs this new variable, which you store as result2
.
Now you make a call through addCount
, which invokes the second function updating the second variable. Then you call result1
logging the first variable (which was never updated), and then you call result2
logging the second variable (which you incremented once).
Upvotes: 5
Reputation: 172
When running the function s1
twice, you generate two variables with the name count, each in the scope of the current method call.
Other than that, your addCount
method is global for both calls. Your second call overrides the first one.
So in the new addCount
method, you have the scope of your second s1
call.
Thus, your call to addCount
has the second count
variable in scope and increments this one.
When printing your results you go back to both scopes and get the correct values of count = 0
in the scope of your first call and count = 1
in the scope of your second.
Upvotes: 0