0

I am having a scoping issue when iterating over an object in coffeescirpt. I had a similar issue with looping over an array, but was able to solve that using forEach, which gave me a new scope for each loop. Now I am having a similar issue except instead of an array, this time I am using an object/dictionary. The problem is that when looping over the object, the last console.log always returns data for the last person in the object, for all the the people. I think this is a scoping issue but I am not sure how to solve it.

for name, data of people
    console.log name
    lookup name, (err, other_data) ->
        console.log data  # this always returns the data for the last person
4

2 回答 2

4

Use a do block:

for name, data of people
    console.log name
    do (data) ->
        lookup name, (err, other_data) ->
            console.log data
于 2013-03-31T02:53:38.000 回答
1

Ionut's answer is correct and I upvoted it.

Just to explain a bit further, the issue you're experiencing is because the callback function you're passing is being run asynchronously in some way. So your loop runs all the way through, and data in the end is set to its final value. The asynchronous callbacks then run one after another, and access the data object. Since the loop has run all the way through, data is always equal to the final value and thats logged.

The do block solves the issue by providing a shorthand for a closure. The code Ionut suggests translates to the following in Javascript:

var data, name, _fn;

_fn = function(data) {
  return lookup(name, function(err, other_data) {
    return console.log(data);
  });
};
for (name in people) {
  data = people[name];
  console.log(name);
  _fn(data);
}

So in this case, the data is passed into a closure function which preserves the current value in its scope and returns the lookup function which then maintains a reference to the value in the closure scope.

于 2013-03-31T03:38:07.043 回答