JavaScript: inline functions vs predefined functions

Can any body throw me some arguments for using inline functions against passing predefined function name to some handler.

I.e. which is better:

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

versus

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


Strange question, but we are almost fighting in the team about this.

Answers:

Answer

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"!

Answer

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

Answer

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:

Answer

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.

Answer

An inline function avoids namespace pollution and predefined functions have higher reuse. I think you could make cases where each is appropriate.

Answer

I think that the only difference in a code like that is that with the second piece of code you can re-call the same function (sometimes with "timer functions" it's useful):

(function(){
  function invokeMe() {
    if(..) setTimeout(invokeMe, 5);
  }
  setTimeout(invokeMe, 5);
})();
Answer

Can't we all just get along?

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

Only one thing really matters, IMO and that's ease of debug. A lot of step tracers won't be able to tell you anything about the func other than the fact that it was anonymous and had args but you can still define inline with a name by putting the definition in parens to force evaluation. For very simple or obvious breaking funcs, I suppose it's not a big deal but to me it's like semis. I really don't care what the other guy does if it doesn't cause pain but I try to always name my funcs because it's not hard and it can be an advantage.

Answer

I know, that this is an old question, but to me there is an even more important difference than the ones already mentioned. hoisting Every function has to be created and therefore reserves some space in memory and eventually has to be GC later.

Named functions get hoisted to the beginning of the surrounding function, and are therefore created on every function call, wether they get used or not. Anonymous functions get created only if the code that defines them is executed.

//an example where you wold prefer to use an anonymous function.
//you can assign this (anonymous) function to a variable, so you get your "name" back.
function someFn(){
    if(condition){
        //the variable declaration has been hoisted, 
        //but the function is created at this point, and only if necessary.
        var process = function(value){/* */};
        switch(condition2){
            case 1: process(valueFor1); break;
            case 2: process(valueFor2); break;
            /* ... */
        }
    }
}

function someFn(){
    var process;
    if(condition){
        process = function(value){ /* A */ }
    }else{
        process = function(value){ /* B */ }
    }

    //beware, depending on your code, "process" may be undefined or not a function
    process(someValue);
}


//an example where you would prefer (/ utilize) the hoisting.
function someFn(){
    /* some code */
    while(condition){
        //some might want to keep the function definition near the code where it is used,
        //but unlike an anonymous function or a lambda-expression this process-function 
        //is created only once per function-call, not once per iteration.
        function process(value, index){ /* ... */ }
        /* ... */
        process(value, index)
    }
}

so, as a rule of thumb:

  • inside a loop there should be no anonymous function or lambda-expression

  • if you need the function only inside of a (rarely true) condition you should prefer anonymous functions over named ones, since they are only created when needed

  • if you know your buisness (JavaScript), you know when to ignore this advice

Answer

The predefined named functions can reduce the JavaScript callback hell issue, which is mentioned at http://callbackhell.com/

Answer

There are no technical reasons to prefer one version over the other. For me is usually depends on two things:

  1. I want to resuse the passed callback in another context. In this case I define the function standalone and pass the reference.
  2. The callback is larger than ~10 lines of code and the function expects additional arguments after the callback. In this case it is hard to reconstruct, which values are actually passed to the function.

Example:

setTimeout(function() { // I need to scroll to see the other arguments

  // many lines of code

}, 0); // <- where does this '0' belong to?
Answer

I prefer to use named functions. Named functions show by name on all debuggers (air, firebug, IE).

Example:

Notice that you can also have inline named functions like

{
    method: function obj_method(){}
}

This way, when you look at the stack trace, you'll see function obj_method instead of anonymous.

Were you asking about when to inline a function rather than declare it? When it makes sense in the code. If you need it from two different places, it can't be inline. Sometimes inline make the code easier to read, sometimes harder.

Answer

I tend towards named functions as well. Anonymous function refs are quick, but should only be used for simple stuff. My rule of thumb is that if the function is more than 2 lines of code, it probably belongs in it's own definition.

This is complicated by most example code making use of Anonymous functions. But the samples are usually very simplistic. The method falls apart as things get more complicated. I've seen function refs nested in function refs as the developer realized that more callbacks were needed in subsequent steps. Instead of this tree based logic, I prefer the organization of isolated functions.

And usually end up happy that I can reuse one of the functions I define later.

One important use of an Anonymous Function is when you need to pass scoped data into your function call, but then I usually just wrap my function into the anonymous function.

Named functions are also absolutely necessary if you ever get into Test Driven Development.

Answer

In the example provided, the declaration and use of the function are so close that I think the only difference is readability. I prefer the second example.

Tags

Recent Questions

Top Questions

Home Tags Terms of Service Privacy Policy DMCA Contact Us

©2020 All rights reserved.