1

In JavaScript, what is the best way to create anonymous function using the current value of a variable, at the moment the anonymous function is created?

This bogus code for example will use the currentObject value at runtime, when the anonymous function is called. So instead to use objects[i], it uses objects[] (which is absolutely normal).

for (var i = 0 ; i < objects.length ; i++) {
    var currentObject = objects[i];
    foo.bind(currentObject.quux, function() {
         bar(currentObject.baz);
    });
}

How best to achieve without an eval() this behavior?

kuroi neko
  • 8,479
  • 1
  • 19
  • 43
Uskiver
  • 845
  • 1
  • 6
  • 6
  • Note: in my production code, I refactored the logic, storing the objects array in a useful variable and creating a more generic anonymous function which takes a parameter matching quux to fetch baz. But I'm interested by the best practices to create anonymous functions matching some constraints. – Uskiver Jan 10 '14 at 13:27
  • 6
    The closure monster has claimed its daily victim... – kuroi neko Jan 10 '14 at 13:27
  • Joke aside, the "bogus" code you show is a bit too bogus for my taste. Binding `foo` is useless since you don't do anything with the resulting function, and using an array of objects simply adds a layer of complexity that has nothing to do with the problem at hand, which is to define a proper closure for the `bar` invokation. Also there is an extra closing brace in the line before last. – kuroi neko Jan 10 '14 at 13:43
  • Some real code would be cool. – Ziggy Jan 10 '14 at 13:45
  • Would have been cool. As answers use the foobar code, it makes sense to keep the question as is. – Uskiver Jan 10 '14 at 13:56

3 Answers3

3

The usual solution is to use an intermediate closure to store your variable :

for (var i = 0 ; i < objects.length ; i++) {
    (function(currentObject){
      foo.bind(currentObject.quux, function() {
         bar(currentObject.baz);
      });
    })(objects[i]);
}

In the next version of EcmaScript, you'll also be able to use let which, contrary to var, creates a variable whose scope is the block and not the function call. The MDN has an example related to your loop problem.

Denys Séguret
  • 372,613
  • 87
  • 782
  • 758
  • let is even supported by IE11+ according http://msdn.microsoft.com/en-us/library/bzt2dkta%28v=vs.94%29.aspx – Uskiver Jan 10 '14 at 13:45
2

You can try this:

for (var i = 0 ; i < objects.length ; i++) {
    var currentObject = objects[i];
    foo.bind(currentObject.quux, (function(val) {
         return function() { bar(val); }
    })(currentObject.baz));
}
Matteo Tassinari
  • 18,121
  • 8
  • 60
  • 81
0
for (var i = 0 ; i < objects.length ; i++) {
    var currentObject = objects[i];
    foo.bind(currentObject.quux, (function(val) {
         return function() {
             bar(val);
         };
    })(currentObject.baz));
}
Maurice Perry
  • 32,610
  • 9
  • 70
  • 97