Rodney_Dian
Rodney_Dian

Reputation: 45

Why does this code have two different results?

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

Answers (4)

Scott Marcus
Scott Marcus

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

Mark Adelsberger
Mark Adelsberger

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

nrausch
nrausch

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

Jordi Castilla
Jordi Castilla

Reputation: 26961

Is because variable addCount has global scope.

Upvotes: 1

Related Questions