jhamm
jhamm

Reputation: 25032

Why is this named anonymous js function working before it is defined?

I have a simple Gulpfile with a task defined. There is a named anonymous function that is defined after the Gulp task. The task uses this function and is working when I would expect to get undefined is not a function, but I am not. Here is the code:

gulp.task('bower', function() {
  var bowerDir = 'bower_components';
  fs.readdir(bowerDir, function(err, dirs) {
    _.each(dirs, function(dir) {
      var directory = dir;
      fs.stat(path.join(bowerDir, dir), function(err, stats) {
        if(stats.isDirectory()) {
          listing('bower_components');
        }
      });
    });
  });
});

var listing = function(dir) {
  console.log(dir);
};

Please explain why this is working?

Upvotes: 0

Views: 177

Answers (2)

jfriend00
jfriend00

Reputation: 707298

gulp.task(), fs.readdir() and fs.stat() are all asynchronous functions. They call their callback functions sometime LATER, not immediately. That means that the code after that defines listing gets a chance to run BEFORE the callback is actually called. So, thus listing is defined before it is actually used.

I wouldn't suggest this as a good coding method myself because you are relying on the timing on things.


If, instead you defined your listing function like this:

function listing(dir) {
  console.log(dir);
}

Then, you would not have a dependency on timing because all statically defined functions like this are parsed first and hoisted to the top of the scope they are defined in and thus always available in that scope ragardless of timing.


FYI, if you really want to show this to yourself, you can add this logging to see the actual timing and sequence of things:

function logTime(msg) {
    console.log((new Date()).getTime() + ": " + msg);
}

logTime("start");
gulp.task('bower', function() {
  var bowerDir = 'bower_components';
  fs.readdir(bowerDir, function(err, dirs) {
    _.each(dirs, function(dir) {
      var directory = dir;
      fs.stat(path.join(bowerDir, dir), function(err, stats) {
        if(stats.isDirectory()) {
          logTime("about to call listing()");
          listing('bower_components');
        }
      });
    });
  });
});

logTime("about to define listing");
var listing = function(dir) {
  logTime("listing() called");
  console.log(dir);
};

Upvotes: 1

Ibrahim
Ibrahim

Reputation: 2062

Because that annonymous function is a callback function and most likely is called after the initialization of listing function.

Upvotes: 0

Related Questions