Archsx
Archsx

Reputation: 972

JavaScript closure and scope

Here are the codes:

function fn() {
  var x = 1;

  function fn2() {
    x++;
    console.log(x);
  }
  return fn2;
}
var foo = fn();
var bar = fn();
foo(); //2
bar(); //2  
foo(); //3

I got a problem that I can't figure out why the result is not 2 3 4.I mean,according the closure principle,foo and bar should have maintain the scope of the function fn,so I thought foo and bar have the same x.Hope you can help me solve the problem.

Upvotes: 1

Views: 71

Answers (4)

JorgeObregon
JorgeObregon

Reputation: 3310

These two are the same call, hence 2 when you invoke them:

var foo = fn();
var bar = fn();

Both set var x=1 privately. Therefore, when you call them again foo(); //3 the inner function fn2 is the one invoked with the increment statement

Upvotes: 0

Nina Scholz
Nina Scholz

Reputation: 386519

You need to call the first function once and build a closure over x then return a function with a function inside.

var fn = function () {        
    var x = 1;
    return function () {
        return function () {
            x++;
            console.log(x);
        };
    };
}();

var foo = fn();
var bar = fn();
foo(); //2
bar(); //3  
foo(); //4

Upvotes: 1

Snowmonkey
Snowmonkey

Reputation: 3761

As var x creates a private variable, it's created anew each time fn() is assigned. If you WANTED it to carry over, simply change var x to this.x:

fn = (function() {
  this.x = 1;

  function fn2() {
    this.x++;
    console.log(this.x);
  }
  return fn2;
});
var foo = fn();
var bar = fn();
foo(); //2
bar(); //3  
foo(); //4

Upvotes: 0

ibrahim mahrir
ibrahim mahrir

Reputation: 31682

foo and bar don't share the same x. x gets created when fn is called. So each call to fn will create a brand new x which will be accessible by the brand defined function fn2 that will be returned.

To check that foo and bar don't share the same x, here is an example:

function fn() {
  var x = 1;

  function fn2() {
    x++;
    return x;
  }
  return fn2;
}
var foo = fn();
var bar = fn();
console.log("foo: " + foo());
console.log("bar: " + bar());
console.log("foo: " + foo());
console.log("foo: " + foo());
console.log("foo: " + foo());
console.log("foo: " + foo());
console.log("bar: " + bar());

Upvotes: 1

Related Questions