2

I'm confused by the following JavaScript code. I wrote a loop and defined a function inside the loop, but when I call a function defined in the loop, I only get 10 rather than the index.

Obviously, in the following code I abstracted out stuff that isn't relevant:

objectArray = [];
for (i = 0; i< 10; i++){
    objectArray[i] = {};   
}
for (i = 0; i< 10; i++){
    objectArray[i].get_number = function(){
        return i;    
    }
}
console.log(objectArray[5].get_number()); // returns 10 rather than 5

I always get 10 rather than i as expected.

  • 1
    What's this `objectArray[i] = {};` supposed to do? – odedta May 07 '15 at 08:45
  • 2
    @odedta It initialises each element to an empty object – James Thorpe May 07 '15 at 08:45
  • 1
    I'm almost positive this is a duplicate, but can't find a decent target right now – James Thorpe May 07 '15 at 08:46
  • 3
    This is the infamous `closure inside a loop` problem. With a closure you have access to the outer scope, so you have access to `i`. BUT (and this is the important part): You access `i` at a point of time where the loop has already finished! Solution: Use a separate scope (e.g. by creating a local copy of i at loop time) and then use the local copy inside the closure function – devnull69 May 07 '15 at 08:46

1 Answers1

1

It's because of JavaScript closure. The method objectArray[i].get_number has direct access to i (not a copy of i). The value of i lives on in memory because each method objectArray[i].get_number still has access to it. There's only one i, and when the loop iterates it, it increases by one. When a method objectArray[i].get_number accesses it, the loop has already run to completion, so it accesses the final value of i.

Luaan
  • 62,244
  • 7
  • 97
  • 116