13
var path;

for (var i = 0, c = paths.length; i < c; i++)
{
    path = paths[i];

    fs.lstat(path, function (error, stat)
    {
        console.log(path); // this outputs always the last element
    });
}

How can I access the path variable, that was passed to fs.lstat function?

3 Answers3

27

This is a perfect reason to use .forEach() instead of a for loop to iterate values.

paths.forEach(function( path ) {
  fs.lstat( path, function(err, stat) {
    console.log( path, stat );
  });
});

Also, you could use a closure like @Aadit suggests:

for (var i = 0, c = paths.length; i < c; i++)
{
  // creating an Immiedately Invoked Function Expression
  (function( path ) {
    fs.lstat(path, function (error, stat) {
      console.log(path, stat);
    });
  })( paths[i] );
  // passing paths[i] in as "path" in the closure
}
gnarf
  • 105,192
  • 25
  • 127
  • 161
  • Be careful with .forEach if your iterable is not exclusively formed with the elements you want to use. I'd rather be use the closure option as a general rule, IMHO. – Dani bISHOP Sep 18 '12 at 12:12
  • @DanibISHOP could you expand on that? Specifically, what is "not exclusively formed with the elements"? – sinisterstuf Aug 29 '15 at 08:37
11

Classic problem. Put the contents of the for loop in another function and call it in the loop. Pass the path as a parameter.

Aadit M Shah
  • 72,912
  • 30
  • 168
  • 299
1

Recursion works nicely here (especially if you have some i/o that must be executed in a synchronous manner):

(function outputFileStat(i) {
    var path = paths[i];

    fs.lstat(path, function(err, stat) {
         console.log(path, stat);
         i++;
         if(i < paths.length) outputFileStat(i);
    });
})(0)
Mark Nguyen
  • 7,168
  • 9
  • 31
  • 41