Hacker News new | past | comments | ask | show | jobs | submit login

    function myFunction(arg1, arg2) {};       // This is OK, but...
    var myFunction = function(arg1, arg2) {}; // This is best!
The second option is better, and is properly scoped, but it leads to certain syntax problems once you get into closures.

What problems? How does assigning the function to a variable help avoid needing to make a closure for this?




The first one will be hoisted to the top of the function (the whole declaration), the second one won't (the variable will, but not the function expression itself).

EDIT: To clarify:

All variable declarations in Javascript do indeed get hoisted to the top of the scope, but with function declarations even the function value itself gets hoisted. So for instance, this returns 'two':

  function foo() {
    function one() { return 'one'; }
    return one();
    function one() { return 'two'; }
  }

  foo();

But this returns 'one':

  function foo() {
    var one = function one() { return 'one'; }
    return one();
    var one = function one() { return 'two'; }
  }

  foo();


What? I have no idea what you are talking about. Both get hoisted to the top of closure scope...


See my edit.


Named functions are generally fine to use (they're hoisted, but otherwise behave the same), but named function expressions (where you both give the function name, and use it as an expression) has some nasty memory leak issues on IE [1].

Some people think its better to ditch named functions completely rather than learn exactly when its problematic and when it's not... which I'm not sure I completely agree with, but its probably a good advice to give to a new JavaScript programmer, as it basically behaves the same minus those issues.

CoffeeScript ended up removing named functions [2] [3] (with the exception of being used for "class" declarations, where its known they're safe) for that reason.

[1] http://kangax.github.com/nfe/#jscript-memory-management

[2] https://github.com/jashkenas/coffee-script/issues/366#issuec...

[3] https://github.com/jashkenas/coffee-script/wiki/FAQ - "Q: Is there any way to name functions, for reflection and recursion?"

edit: formatting


The memory leak issues you're referring to are old and have been fixed. They may be an issue if you are writing code that must support legacy IE, and then only in specific cases. However, if that's not you, then there's no reason not to use named function expressions. There's no other way to completely avoid arguments.callee (which is going away) for recursive reference, and it also makes call stacks and debug messages clearer. You won't think either of those are a real issue until they are.

So no, I disagree that that's good advice to give to a new programmer.


The memory leaks issues are effecting IE <= 8, which still has around 10% market share. Losing one of ten potential customers is not acceptable for most businesses. Unless you're writing server-side JavaScript, or have a specific demographic that uses newer technologies, those kind of bugs are not something that you should ignore.

To address your other points - you can get a recursive reference by simply assigning your function to a variable, `var f = function(){ f(); }`. There's no need for named functions for that.

As for call stacks and debug messages - that was true some time ago, but modern debugging tools can figure out the function name pretty good even if it isn't a named function. I work with CoffeeScript code(who doesn't have named functions) and stack traces are fine.

I think its a better practice to avoid named function expressions on client-side code. Non-expression named functions are fine, but considering that named function doesn't actually have any benefit (I don't consider hoisting a benefit - I prefer to have my functions declared before they're used), I can see why some people would decide to just avoid them altogether.

edit: spelling


> To address your other points - you can get a recursive reference by simply assigning your function to a variable, `var f = function(){ f(); }`. There's no need for named functions for that.

> (I don't consider hoisting a benefit - I prefer to have my functions declared before they're used)

> As for call stacks and debug messages - that was true some time ago, but modern debugging tools can figure out the function name pretty good even if it isn't a named function.

All of these ignore the fact that functions are not simply declared once in Javascript and then used later, like in C. It's a dynamic language with first-class functions and function literals. You could assign to a variable in this case, but that's needlessly restricting:

  asyncFunc(function cb(result) { print(result); });
As for IE and memory leaks, I already acquiesced to the need to support it in some cases. Still, for many people it is acceptable to drop support for IE8 despite its general market share, and this leak may not be an issue if the function in question is not related to repeating code. Certainly you should not ignore the issue.


  > All of these ignore the fact that functions are not simply declared once in Javascript and then used later, like in C. It's a dynamic language with first-class functions and function literals. You could assign to a variable in this case, but that's needlessly restricting:
  >
  >   asyncFunc(function cb(result) { print(result); });
The assignment itself is an expression too, that returns the assigned value - the function in that case. You can just do that:

  var cb;
  asyncFunc(cb = function(result) { print(result); })
I would agree that having to declare the variable separately is a bit annoying, but I'm mostly writing CoffeeScript which doesn't require you to explicitly declare variables, so it doesn't really bother me.

Other than hoisting and leaking memory, nameless function expressions can be used to anything that can be done with named functions.




Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: