views:

371

answers:

9

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

A: 

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?
Fabian Jakobs
+3  A: 

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.

jsight
+1 for combining a duel, a good answer and bike shed :)That's also how we got general approval here: by limiting inline function to a few lines.
Danny T.
+1 for the "full duel" comment. -1 for the bikeshedding comment. There is actually a very significant (read: non-trivial) difference between the two forms, even without reuse.
T.J. Crowder
@TJ Crowder - Sure, there are significant differences. My assumption was that the differences weren't really relevant to their debate (ie, both forms function similarly well in the case they are discussing, and some devs are just arguing based on style (even if they say otherwise)). But you're right "Any argument" is an exhaggeration. :)
jsight
Thanks for the bikeshedding link, somehow had not seen that before.
bmoeskau
+2  A: 

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:

CMS
thanks for article! really useful
glaz666
Naming a function is also the best way to avoid memory leaks.
HeavyWave
@HeavyWave: What you said needs clarification. It's true that functions that create closures are more prone to memory leaks (if you're not careful) and even if not causing a memory leak, they use more memory than they need (because you don't really usually need all the variables in the closure).However, naming a function does not mean you're avoiding the closure. Using a global named function does. But who wants write a serious js app with a bunch of global functions? It's OK for web page enhancement. In that case, though, memory is not much of a concern.
Juan Mendes
@Juan Mendes, you are totally right. I should have clarified what I meant. Of course, simply naming a function does not guarantee there will be no leaks. I just wanted to point out that abuse of anonymous functions can lead to serious memory leakage issues, which can be crucial for web applications.
HeavyWave
A: 

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);
})();
mck89
note that you can also do this with `arguments.callee`.
Pointy
@Pointy: True -- at a *serious* performance cost in nearly all implementations (we're talking orders of magnitude here), and not in the new "strict" mode.
T.J. Crowder
@TJ wow thanks, that's good to know
Pointy
@Pointy: Yeah, I was really shocked when I learned about the performance aspect.
T.J. Crowder
@TJ I'm guessing you've seen the stuff about IE w.r.t. named functions used as rvalues http://yura.thinkweb2.com/named-function-expressions/ still that's a really good article
Pointy
@Pointy: LOL, oh yes, I know kangax from our mutual involvement in Prototype. In fact, that very article is referenced in the article on my blog I linked to in my answer. ;-) And it's not just IE, at the time he wrote that article, lots of implementations had issues.
T.J. Crowder
@TJ thanks - good article
Pointy
+3  A: 

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. :-)

T.J. Crowder
+1 for the only objective answer.
Mark
@Mark: Thanks. Yours isn't objective? Seems like it is to me.
T.J. Crowder
@TJ The reuse is, but that's pretty obvious. At what point the abundance of names becomes pollution would be subjective, as well as any readability argument. It's hard to argue with more details in the stack trace.
Mark
+1 for this "Rules are meant to be broken, though, not slavishly bowed to"
plodder
+1  A: 

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

Mark
In his example, there is basically *no* namespace pollution in either case. He has the whole thing wrapped in a scoping function, thereby creating a well-defined, contained namespace for the named function. No global is created.
T.J. Crowder
@T.J. True, but taking his example literally, there is nothing to debug in a call stack either and no information needed from the tools. ;)
Mark
@Mark: We have no idea what complex logic is going to be where `/*code*/` is! :-) It may well call a function which calls another function which calls (etc., etc.), and he may well need to debug that. (Or it may just set the document title to "Foo!" which seems unlikely to need debugging.)
T.J. Crowder
@TJ: I know. :) I was more just trying to point out there are assumption made in all the answers. One being the code in `/*code*/` is non-trivial, and one that there is more enclosed in the scoping function than included in the example.
Mark
@Mark: Ennh, *okay*. :-) But I will just point out that in the one case he did actually say (effectively) "There's code here." But still, as you say, assumptions.
T.J. Crowder
A: 

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.

lincolnk
A: 

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.

Juan Mendes
@Juan: That named function expression (`method: function obj_method(){}`) doesn't work in most JavaScript implementations (including IE's JScript). It *should* work, arguably, but it doesn't. For more, see Juriy Zaytsev's article on NFEs: http://yura.thinkweb2.com/named-function-expressions/ (This link is actually in one of the other answers, and also in a comment on *another* answer.)
T.J. Crowder
@TJ I read the part about Function names in debuggers. That article explains that there are some quirks, it doesn't say that inline named functions don't work in IE. Most of the quirks can be worked around by making sure you never have two functions with the same name under the same scope. So if you have a block that will decide which function to return just name them accordingly, like addEventIE and addEventStandard and you'll be fine.The article actually says: "What it all boils down to is the fact that named function expressions is the only way to get a truly robust stack inspection."
Juan Mendes
A: 

There is an actual technical difference: if you create an anonymous function inside another function and assign it to anything outside of the parent function (like a button onclick event), then this piece of code will stay in memory forever, thus a memory leak (at least in IE and Firefox). If you are writing an online application, than you should avoid anonymous functions.

It is a great feature of Javascript, but unfortunately it leads to problems, which can later become too difficult to tackle.

HeavyWave