Node.js Callbacks – Understanding the Nature of Callbacks

node.js

In the plain javaScript world I've learned that nested functions can be problematic because the inner function is "re-created" every time the outer function is called:

function outer(a) {
    function inner(arg1,arg2){
        return arg1 + arg2;
    }
    return inner(a, 6);
}
myVar = outer(4);

Apparently the inner function is garbage collected and the constant re-creation of it has a cost on performance. This could be re-factored as:

function inner(arg1, arg2) {
    return arg1 + arg2;
}

function outer(a) {
    return inner(a, 6);
}

myVar = outer(4);

If I am correct it seems that the tradeoff lies in the changing scope of inner; the fact that function inner no longer has access to outer's own variables. If I am correct so far, lets move to Node.JS. Node is heavy on callbacks, and my question is, are asynchronous callback functions typical in Node also "re-created" every time they are fired? Take the following common Node construct:

http.createServer(function (req, res) {
    res.writeHead(200, {'Content-Type': 'text/plain'});
    res.end('Hello World\n');
}).listen(1337, '127.0.0.1');

In reality the function can get pretty large; it can encompass a lot of functionality. Is the above callback "re-created" every time a client GETs or POSTs the server? If so, would it be better to always de-couple the callbacks as in the plain javaScript example:

function handleGET(req, res) {
   res.writeHead(200, {'Content-Type': 'text/plain'});
   res.end('Hello World\n');
}

http.createServer(handleGET).listen(1337, '127.0.0.1');

as a related bonus question, are event functions re-created too? Would they benefit from prior declaration?

myObj.on('someEvent', function someFunction() {...});

vs.

function someFunction() {...}
myObj.on('someEvent', someFunction);

Best Answer

http.createServer(function (req, res)
{
    // do stuff
});

is almost exactly the same as

function handler (req, res)
{
    // do stuff
}

http.createServer(handler);

The arguments passed to a called function are evaluated in the same scope as the call. Now, if you had done something like:

http.createServer(function (req, res)
{ 
  function handler (req, res)
  {
    // do stuff
  }
  return handler(req, res);
});

Then yes, you'd be creating a new function for every request, and that would be inefficient. In terms of something like a web server this is usually not a problem since the request handlers are often declared in a single place.

The only time you really want to nest functions (which is quite different from passing a function as an argument, as you are doing in your examples), is when you need references to the enclosing scope's variables (ie: a closure)

In answer to your second question, no. There's nothing different about event handler functions, and both your examples are functionally equivalent, and should essentially compile to the same machine code.