简体   繁体   中英

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?

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" 

The way you assigned a1 , a2 , and a3 all to the same object means they are all different names for the same thing , ie they all reference the same object.

Your for loop then runs three times, creating three anonymous functions. In each function, j has a different value, so you would expect running those functions to show three different values when you call fu() .

However , since a1 , a2 , and a3 are all the same, each iteration of the loop overwites the previous fu() , until you're left only with the one with the embedded value of j being 3 .

Run the code with different assignment, and watch how the behavior changes to what you were originally expecting:

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

See every variable like a pointer to an object : var a = b = c = {}; is equal to :

a
 \
  \
b-- {}
  /
 /
c

You don't use the same variable to access the object but you modify the same object every time.

try:

a.test = 'fromA';
console.log(b.test); //fromA
console.log(c.test); //fromA

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM