Reputation: 363
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?
Upvotes: 2
Views: 338
Reputation: 181
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
Upvotes: 2
Reputation: 87203
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"
Upvotes: 5
Reputation: 7288
The way you assigned a1
, a2
, and a3
all to the same object means they are all different names for the same thing, i.e. 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 = {};
Upvotes: 4