While I'm waiting for the faq to load so I can see if it says there in a
manner that I can find, what's the difference between the function
definition:
var x = function(y)
{
// do something
return;
}
and the function definition:
function x(y)
{
// do something
return;
}
and why might someone choose to use one form over the other when their
function calls are of the form:
x(y);
Hi,
According to the excellent JavaScript Patterns book, by Stoyan Stefanov,
Chapter 4 - Functions, section "Declarations Versus Expressions: Names
and Hoisting" (p. 59):
- Function declarations can only appear in 'program code', meaning
inside of the bodies of other functions or in the global space. Their
definitions cannot be assigned to variables or properties, or appear in
function invocations as parameters;
- the availability of the read-only name property of the function
definition pattern. This property is not standard but available in many
environments. In function declarations and named function expressions,
the name property is defined. In anonymous function expressions, it
depends on the implementation; it could be undefined (IE) or defined
with an empty string (Firefox, WebKit) [...] The name property is useful
when debugging code in Firebug or other debuggers. When the debugger
needs to show you an error in a function, it can check for the presence
of the name property and use it as an indicator. The name property is
also used to call the same function recursively from within itself. If
you were not interested in these two cases, then an unnamed function
expression would be easier and less verbose.
*And finally, the most important difference IMO lies in the hoisting
behavior*:
[...] all variables, no matter where in the function body they are
declared, get hoisted to the top of the function behind the scenes. The
same applies for functions because they are just objects assigned to
variables. The only “gotcha†is that when using a function declaration,
the definition of the function also gets hoisted, not only its
declaration. Consider this snippet:
// antipattern
// for illustration only
// global functions
function foo() {
alert('global foo');
}
function bar() {
alert('global bar');
}
function hoistMe() {
console.log(typeof foo); // "function"
console.log(typeof bar); // "undefined"
foo(); // "local foo"
bar(); // TypeError: bar is not a function
// function declaration:
// variable 'foo' and its implementation both get hoisted
function foo() {
alert('local foo');
}
// function expression:
// only variable 'bar' gets hoisted
// not the implementation
var bar = function () {
alert('local bar');
};
}
hoistMe();
In this example you see that, just like with normal variables, the mere
presence of foo and bar anywhere in the hoistMe() function moves them to
the top, overwriting the global foo and bar. The difference is that
local foo()’s definition is hoisted to the top and works fine; although
it’s defined later. The definition of bar() is not hoisted, only
its declaration. That’s why until the code execution reaches bar()’s
definition, it’s undefined and not usable as a function (while still
preventing the global bar() from being “seen†in the scope chain).
I'd strongly suggest that you purchase and read this book carefully.
Cheers,
Joao Rodrigues (J.R.)