0

I'm working on a code where I must pass a different function to some objects.

In this case, I'm trying to pass a different function for the onchange event. So currently what I got is something like this this:

var ArrayList; //Contains some data to use with ObjectArray format { n: data }
var ObjectArray; //Contains several objects format Array[n] = Object;
for(var key in ArrayList){
    var doFunction = function() {
        Object[key].doSomething(ArrayList[key]);
    }
    Object[key].onchange = doFunction;
}

The problem here I believe is that I'm afraid it will execute the code as it is declared and not with the values of the actual variables.

Is there a way to pass the function with the values as it executes? or will the variables get parsed the way its written?

MinusFour
  • 13,913
  • 3
  • 30
  • 39
  • In your declaration above, the onchange will trigger the function and not before – mplungjan Jul 24 '12 at 18:34
  • 1
    But this is also valid: for(var key in ArrayList){     Object[key].onchange = function() {        doSomething(ArrayList[key]);     }   } ---- do watch out for closures – mplungjan Jul 24 '12 at 18:36
  • By trigger do you meant that it will execute on that moment or per example, that in doFunction there won't be an Object[key] but rather a Object[0]? – MinusFour Jul 24 '12 at 18:54
  • possible duplicate of [Javascript infamous Loop problem?](http://stackoverflow.com/questions/1451009/javascript-infamous-loop-problem) – katspaugh Jul 24 '12 at 19:54

2 Answers2

2

It's the classic function in a loop problem. You need to understand how closures work.

Read the "Example 3" part of this answer carefully. The whole How do JavaScript closures work? question, too.

Another example that might help understand intuitively:

var key = 5;

var onchange = function () {
    console.log(key);
};

onchange(); // 5

key = 10; // the loop reassigns the key on each iteration

onchange(); // 10
Community
  • 1
  • 1
katspaugh
  • 17,449
  • 11
  • 66
  • 103
  • 1
    Thanks a lot, this helped me understand a little bit. I'm afraid it's not 100% understood, but I know what to avoid now. I'll just need to read all of it slowly. – MinusFour Jul 24 '12 at 21:18
1

This is how it should be done:

var ArrayList; //Contains some data to use with ObjectArray format { n: data }
var ObjectArray; //Contains several objects format Array[n] = Object;
for(var key in ArrayList)
{
    (function(key)
    {
        var doFunction = function() 
        {
            Object[key].doSomething(ArrayList[key]);
        }
        Object[key].onchange = doFunction;
    }(key))    
}
katspaugh
  • 17,449
  • 11
  • 66
  • 103
spaceman12
  • 1,039
  • 11
  • 18
  • Would it work differently if I'd remove the Object[key].onchange = doFunction; and return doFunction instead and add Object[key].onchange = (function (key) { ... })(key) ? – MinusFour Jul 25 '12 at 11:45
  • You could do it this way - (function(key){Object[key].onchange=Object[key].doSomething(ArrayList[key]);}(key)) – spaceman12 Jul 25 '12 at 11:53
  • Like - Object[key].onchange = (function(key) var do Function = function() { Object[key].doSomething(ArrayList[key]); } return doFunction; }(key)); – MinusFour Jul 25 '12 at 15:30
  • No, you cannot do it that way inside a loop or otherwise all the objects will be assigned the same value throughout! And returning a value inside the loop will not only breaks off the loop but completely exits you out from that function – spaceman12 Jul 25 '12 at 22:21