I learned something: I didn't know that the difference between:
function foo() {
}
and
var foo = function() {
};
Was that with the first form foo() will always be declared and available for use inside a scope, while the second form depends at which point it is declared.
But I had read somewhere (can't remember where... jshint?) a long while ago that using the latter form inside scopes was better, so I've adopted that.
I don't think I will go with the guide for this one, since not having the function defined automatically is often useful, to avoid overhead of instantiating the function for when it's not going to be used due to code flow.
This is referred to as "hoisting". As an aside, technically the latter's `var` declaration also gets destructured and hoisted as such...
var foo;
...
foo = function() {
}
Also another difference in the latter is that its an anonymous function, which is commonly seen in assignment expressions — but you could also name it for more informative logging.
Nice trick, thanks! The "anonymous" function is especially annoying when profiling code, so that should address that annoyance. I often struggle with picking names, but another post here shows that "foo" can just be reused as the function name.
> I often struggle with picking names, but another post here shows that "foo" can just be reused as the function name.
I'd be very careful about giving them the same name if you're working with IE at all. IE8 and below's JScript does some really strange stuff with function expressions, leaking and hoisting them all over the place. [1]
Instead, I'd just append a character or something to differentiate the two. I've been using the format advocated for in Javascript Patterns[2][3]:
A lot of people prefer the latter form inside scope, because it disambiguates the ambiguity that hoisting introduces: define your function at the bottom of the scope, and it'll still be available at the top. By assigning it to var, you delineate "this function can be called by any line in this scope after this one, but not by any line before it." You also remove a named reference to it from the stack trace.
I much prefer dealing with the "weird" "confusion" hoisting behavior than with not having a named function in my stack trace.
Ah, right. Should have left the original comment alone.
Here's why you shouldn't rely on function hoisting: it gets weird. Weird enough that MDN has a section on it's "oddities" [0]. And since it doesn't add any expressive power, there's no compelling reason not to just treat all your code as data.
Or limiting when/where you define named functions it's pretty damn silly to declare a named function within an if block within a function call, especially if it has the same name as a function you've defined outside of it.
I tend to limit them to "private" module functions. e.g.,
"use strict";
/*global module:true*/
function add(a, b) {
return a+b;
}
module.exports = {
sum : function(list) {
return list.reduce(add, 0);
}
};
I don't declare named functions in a scope smaller than the module itself, so I don't really run into the 'weirdness' of hoisting.
Then again, I've moved to commonjs style modules for everything - server side with node, client side with browserify (webpack does weird things with require()).
I'd be in complete agreement if it offered any substantive benefits; however, I've yet to see an example of function-hoisting that can do something regular var-hoisting can't.
Yes, actually it does. A named function expression and a function declaration are distinct concepts. The latter is function-hoisted (the whole body goes to the top), whereas the former is only var-hoisted (the body remains in place).
What browser are you using? As far as I can tell, all modern browsers know how to get the name of a function defined like `var foo = function(){}` for stack traces.
With overhead, the approach I try to stick to is unless the code become more difficult to grasp, avoid overheads, however small they may be, whenever they can be avoided. Everything adds up in the end.
But I had read somewhere (can't remember where... jshint?) a long while ago that using the latter form inside scopes was better, so I've adopted that.
I don't think I will go with the guide for this one, since not having the function defined automatically is often useful, to avoid overhead of instantiating the function for when it's not going to be used due to code flow.