JavaScript: inline functions vs predefined functions

Solution 1:

Named functions

There is some serious misuse of terminology in the question and answers on this page. There is nothing about whether or not a function is inline (a function expression) that says you cannot name it.

This is using a function expression:

setTimeout(function doSomethingLater() { alert('In a named function.'); }, 5);

and this is using a function statement:

function doSomethingLater() { alert('In a named function.'); }
setTimeout(doSomethingLater, 5);

Both examples are using named functions and both get the same benefits when it comes to debugging and profiling tools!

If the name is specified (the text after "function" but before the parenthesis) then it is a named function regardless of whether it is inline or declared separately. If the name is not specified then it is "anonymous".

Note: T.J. points out that IE mishandles named function expressions in a non-trivial way (See: http://kangax.github.com/nfe/#jscript-bugs) and this is important to note, I'm simply trying to make a point about the terminology.

Which should you use?

In response to your direct question, you should use a named function statement if the function could ever be used from any other place in your code. If the function is being used in exactly one place and has no relevance anywhere else then I would use a function expression unless it is prohibitively long or otherwise feels out of place (for style reasons). If you use an inline function expression then it is often useful to name it anyway for the purposes of debugging or code clarity.

Memory leaks

Whether you name your function, use a function statement, or use a function expression has little impact on the memory leak issue. Let me try to explain what causes these leaks. Take a look at this code:

(function outerFunction() {
    var A = 'some variable';

   doStuff();
})();

In the code above, when "outerFunction" finishes "A" goes out of scope and can be garbage collected, freeing that memory.

What if we add a function in there?

(function outerFunction() {
    var A = 'some variable';

   setTimeout(function(){ alert('I have access to A whether I use it or not'); }, 5);
})();

In this code (above) the function expression we are passing to setTimeout has a reference to "A" (through the magic of closure) and even after "outerFunction" finishes "A" will remain in memory until the timeout is triggered and the function is dereferenced.

What if we pass that function to something other than setTimeout?

(function outerFunction() {
    var A = 'some variable';

   doStuff(function(){ alert('I have access to A whether I use it or not'); });
})();

function doStuff(fn) {
    someElement.onclick = fn;
}

Now the function expression we are passing to "doStuff" has access to "A" and even after "outerFunction" finishes "A" will remain in memory for as long as there is a reference to the function we passed into doStuff. In this case, we are creating a reference to that function (as an event handler) and therefore "A" will remain in memory until that event handler is cleared. (e.g. someone calls someElement.onclick = null)

Now look at what happens when we use a function statement:

(function outerFunction() {
    var A = 'some variable';

    function myFunction() { alert('I have also have access to A'); };
    doStuff(myFunction);
})();

The same problem! "myFunction" will be cleaned up only if "doStuff" does not hold a reference to it and "A" will only be cleaned up when "myFunction" is cleaned up. It does not matter whether we used a statement or an expression; what matters is if a reference to that function is created in "doStuff"!

Solution 2:

There is one significant difference between the two: The latter one has a name.

I like to help my tools help me, and so I mostly avoid anonymous functions as my tools can't give me meaningful information about them (for instance, in a call stack list in a debugger, etc.). So I'd go with the

(function(){
  function invokeMe() {
    /*code*/
  }
  setTimeout(invokeMe, 5);
})();

...form in general. Rules are meant to be broken, though, not slavishly bowed to. :-)

Note that according to the specification, there's a third alternative: You can have an inline function that also has a name:

(function(){
  setTimeout(function invokeMe(){ /*some code here*/ }, 5);
})();

The problem, though, is that every version so far of the JavaScript interpreter from Microsoft ("JScript"), including (astonishingly) the one in IE9, handles that named function expression incorrectly and creates two completely distinct functions at different times. (Proof, try it in IE9 or earlier and also in just about any other browser.) IE gets it wrong in two ways: 1. It creates two separate function objects, and 2. As a consequence of one of those, it "bleeds" the name symbol into the enclosing scope of the expression (in clear violation of Section 13 of the specification). Details here: Double take

Solution 3:

IMO, declaring a function will be useful only if you intend to re-use it later, in some other way.

I personally use function expressions (first way) for setTimeout handlers.

However you might want to know the differences between function declarations and function expressions, I recommend you the following article:

  • Named function expressions demystified

Solution 4:

I suggest a full duel between opposing team members to settle such arguments.

More seriously, in the end it just doesn't matter. The first form (non-named functions) tends to get unwieldy with larger functions, but isn't a big deal at all with small (1-2 line) functions. The second form is similarly harmless.

Any argument against either style is pure bikeshedding, imo.