Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

JS closure for mutable variables

Please help me find the reason why the local "j" variable continues to change during the loop:

var a1 = a2 = a3 = {};

for (var i = 1; i < 4; i ++ ) {
  (function(j){
    console.log(j);
    window['a'+j].fu = function(){
      console.log('fu:',j);
    };
  })(i);

}

a1.fu(); // returns "fu:,3" - why not 1?

a2.fu(); // returns "fu:,3" - why not 2?

a3.fu(); // returns "fu:,3"

I read the nice answer on similar issue, but it's not working for my case. Mutable variable is accessible from closure. How can I fix this?

like image 278
alex23 Avatar asked Jun 10 '26 17:06

alex23


1 Answers

Object assignment does not make copy of the objects, the same object is referenced by all the three variables. So, even changing the value inside the loop will update the same location for different object.

The value in the object is set as 3 in the last iteration of the loop and when retrieving the value after for loop, the value 3 is returned for all the variables.

When you create objects

var a1 = a2 = a3 = {};

all the three variables refer to the same object.

Solution to the problem can be declaring the object individually.

var a1 = {},
    a2 = {},
    a3 = {};

for (var i = 1; i < 4; i++) {
  (function(j) {
    console.log(j);
    window['a' + j].fu = function() {
      console.log('fu:', j);
    };
  })(i);
}

a1.fu(); // returns "fu:,3" - why not 1?

a2.fu(); // returns "fu:,3" - why not 2?

a3.fu(); // returns "fu:,3"
like image 72
Tushar Avatar answered Jun 12 '26 08:06

Tushar