Nikhil Baliga
Nikhil Baliga

Reputation: 1341

Value gets overwritten because of access by reference

a = [];
for (var i = 0; i < 3; i++) {
   a.push(function() {
      console.log(i);
   })
}

a[0]()     // I want 0, but I get 3

I am trying to write a simple piece of code where I have an array of functions such that when I execute a function at a particular index, the index value should get printed.

However, the piece of code above shows the same result (3 in this case) for all index values. I understand that the value is pointing by reference and therefore points to the last value of i. Could someone point out how to do this in the right manner?

Upvotes: 0

Views: 51

Answers (3)

Mr. Polywhirl
Mr. Polywhirl

Reputation: 48630

Here is an alternate version to an anonymous function that gets created and executed all at once.

The issue that you are having is that when the function gets called, the loop has already been evaluated and the value of i has already reached the max value of 3. You need trap the current value of i while the loop is being evaluated.

var a = [];

for (var i = 0; i < 3; i++) {
  var fn = function() {
    console.log(arguments.callee.i);
  }
  fn.i = i; // Pass as 'i' parameter to 'fn'.
  a.push(fn);
}

a[0](); // The value 0 will be printed, rather than 3.

There is more than one way to skin a cat. The code above is very similar to:

var a = [];

function fn(i) {
  return function() {
    console.log(i);
  }
}

for (var i = 0; i < 3; i++) {
  a.push(fn(i));
}

a[0](); // The value 0 will be printed, rather than 3.

Upvotes: 0

adricadar
adricadar

Reputation: 10219

You can add a self executing function to act like a module. Doing this, the scope of the variable i is in that function.

a = [];
for (var i = 0; i < 3; i++) {
   (function(i){
       a.push(function() {
           alert(i);
       })
   })(i);
}

a[0]() 

Note: In this block (function(i){ ... })(i), i can have any name, there is no connection between i from loop and i from function, i.e. (function(r){ ... })(r).

Upvotes: 1

Zee
Zee

Reputation: 8488

Wrap it around a function. Now each time the loop executes, the wrapper function has its own value of i.

a = [];
for (var i = 0; i < 3; i++) {
    (function(i){
        a.push(function() {
            console.log(i);
        })
   })(i);
}

a[0]() 

Upvotes: 2

Related Questions