491

What is the difference between the following lines of code?

//Function declaration
function foo() { return 5; }

//Anonymous function expression
var foo = function() { return 5; }

//Named function expression
var foo = function foo() { return 5; }
  • What is a named/anonymous function expression?
  • What is a declared function?
  • How do browsers deal with these constructs differently?

What do the responses to a similar question (var functionName = function() {} vs function functionName() {}) not get exactly right?

Community
  • 1
  • 1
Faisal Vali
  • 29,823
  • 8
  • 40
  • 45
  • Here's [a good article on named function expressions](http://kangax.github.com/nfe). Function expressions vs declarations are addressed in the first section. – Evan Meagher Jun 18 '09 at 17:09
  • The main difference IMO is hoisting. Here is a good article on the topic: http://www.adequatelygood.com/JavaScript-Scoping-and-Hoisting.html – Ryan Wheale Nov 18 '14 at 18:03

5 Answers5

414

They're actually really similar. How you call them is exactly the same.The difference lies in how the browser loads them into the execution context.

Function declarations load before any code is executed.

Function expressions load only when the interpreter reaches that line of code.

So if you try to call a function expression before it's loaded, you'll get an error! If you call a function declaration instead, it'll always work, because no code can be called until all declarations are loaded.

Example: Function Expression

alert(foo()); // ERROR! foo wasn't loaded yet
var foo = function() { return 5; } 

Example: Function Declaration

alert(foo()); // Alerts 5. Declarations are loaded before any code can run.
function foo() { return 5; } 


As for the second part of your question:

var foo = function foo() { return 5; } is really the same as the other two. It's just that this line of code used to cause an error in safari, though it no longer does.

Flip
  • 4,701
  • 5
  • 32
  • 63
Khon Lieu
  • 4,165
  • 1
  • 12
  • 2
  • 32
    The last one is not the same than ``var foo = function() { return 5; }``. Because here, ``foo.name`` is ``''``, in the last one it is ``'foo'``. – jonathancardoso Feb 02 '13 at 20:53
  • 2
    @JCM AFAIK, the name property is not part of ECMAScript and is only implemented in some browsers. [`Function.name` at MDN](https://developer.mozilla.org/en-US/docs/JavaScript/Reference/Global_Objects/Function/name) – Zach Lysobey Apr 02 '13 at 20:55
  • 7
    @ZachL Just used as example, what I wanted to say is that the second function has a name, where the first one doesn't. – jonathancardoso Apr 02 '13 at 23:58
  • 3
    "But if you call a function declaration, it'll always work." So then is there ever a benefit of using a function expression? Why not just always use declarations? – Richie Thomas Oct 02 '14 at 18:29
  • 4
    It's actually considered a best practice to use function expressions as then the behavior is more intuitive than with declarations. It reads better as it follows a logical flow, You define it and then call it, if you don't you get an error, which is the expected behavior. Actually I think function declarations are not allowed in non function scopes...I recommend this post on the subject: http://javascriptweblog.wordpress.com/2010/07/06/function-declarations-vs-function-expressions/ – Lior Oct 14 '14 at 10:22
  • 1
    Check `function` hoisting in javascript for more clarifications. http://www.adequatelygood.com/JavaScript-Scoping-and-Hoisting.html – Samar Panda Nov 18 '14 at 16:52
  • 1
    Thanks for the explanation, but what is the use of having function expressions over function declarations ? – Yogi Jan 23 '16 at 05:35
  • 1
    Can I assume that *Function Expression* implements kind of *lazy* behaviour, similar to lazy initialization? I mean, it gets loaded only upon the request of interpreter. – Mike B. Apr 24 '17 at 09:06
111

Function Declaration

function foo() { ... }

Because of function hoisting, the function declared this way can be called both after and before the definition.

Function Expression

  1. Named Function Expression

    var foo = function bar() { ... }
    
  2. Anonymous Function Expression

    var foo = function() { ... }
    

foo() can be called only after creation.

Immediately-Invoked Function Expression (IIFE)

(function() { ... }());

Conclusion

Crockford recommends to use function expression because it makes it clear that foo is a variable containing a function value. Well, personally, I prefer to use Declaration unless there is a reason for Expression.

Emile Bergeron
  • 14,368
  • 4
  • 66
  • 111
geniuscarrier
  • 3,989
  • 2
  • 19
  • 15
  • 10
    Welcome to Stack Overflow! Thanks for posting your answer! Please be sure to read the [FAQ on Self-Promotion](http://stackoverflow.com/faq#promotion) carefully. Also note that it is *required* that you post a disclaimer every time you link to your own site/product. – Andrew Barber Nov 20 '12 at 20:03
  • 1
    point of interest: js is case-sensitive. Your caps-locked examples don't work ;-) – Zach Lysobey Apr 02 '13 at 20:59
  • 1
    also, you *can* have a Named IIFE: `(function myFunc() { ... }());` – Zach Lysobey Apr 02 '13 at 21:00
  • 1
    Shorter and widely used way to write IIFE: If you don't care about the return value, or the possibility of making your code slightly harder to read, you can save a byte by just prefixing the function with a unary operator. Example: `!function(){ /*code*/ }();` (source: [linked article](http://benalman.com/news/2010/11/immediately-invoked-function-expression/#iife)) – naXa Aug 05 '14 at 09:24
  • @naXa - +1 for the link, well written article on IIFE :) – mlo55 Feb 20 '16 at 13:19
  • `function hoisting` & `variable hoisting` & `IIFE` – xgqfrms Jun 25 '17 at 06:24
  • As my investigation, any functions in an expression will be function expression. – hiveer May 16 '18 at 09:07
20

Regarding 3rd definition:

var foo = function foo() { return 5; }

Heres an example which shows how to use possibility of recursive call:

a = function b(i) { 
  if (i>10) {
    return i;
  }
  else {
    return b(++i);
  }
}

console.log(a(5));  // outputs 11
console.log(a(10)); // outputs 11
console.log(a(11)); // outputs 11
console.log(a(15)); // outputs 15

Edit: more interesting example with closures:

a = function(c) {
 return function b(i){
  if (i>c) {
   return i;
  }
  return b(++i);
 }
}
d = a(5);
console.log(d(3)); // outputs 6
console.log(d(8)); // outputs 8
TomTom
  • 1,669
  • 1
  • 11
  • 14
  • 7
    You don't need to declare the function with a different name to make it recursive. In fact, I'd say that confuses things. `a = function a(i)` and doing `return a(++i)` produces the same result – PhilT Jul 09 '13 at 16:46
  • 1
    But using a different name for the function than the variable illustrates the point more clearly. Kudos for providing an example for usage of named function expressions. – gfullam Aug 07 '15 at 12:58
12

The first statement depends on the context in which it is declared.

If it is declared in the global context it will create an implied global variable called "foo" which will be a variable which points to the function. Thus the function call "foo()" can be made anywhere in your javascript program.

If the function is created in a closure it will create an implied local variable called "foo" which you can then use to invoke the function inside the closure with "foo()"

EDIT:

I should have also said that function statements (The first one) are parsed before function expressions (The other 2). This means that if you declare the function at the bottom of your script you will still be able to use it at the top. Function expressions only get evaluated as they are hit by the executing code.

END EDIT

Statements 2 & 3 are pretty much equivalent to each other. Again if used in the global context they will create global variables and if used within a closure will create local variables. However it is worth noting that statement 3 will ignore the function name, so esentially you could call the function anything. Therefore

var foo = function foo() { return 5; }

Is the same as

var foo = function fooYou() { return 5; }
Alex
  • 30,072
  • 10
  • 51
  • 67
  • 24
    `fooYou` is not ignored. It is visible in function body, so the function can reference itself (e.g. to implement recursion). – el.pescado Jul 27 '10 at 14:06
  • 2
    That's a good point. I didn't think about that :) – Alex Apr 30 '11 at 08:59
  • 7
    Also, named function expressions are useful for debugging: `var foo = function fooYou() { return 5; }; console.log(foo); console.log(foo.name);` will print `fooYou() / fooYou` (Firefox), `[Function: fooYou] / fooYou` (node.js), `function fooYou() { return 5; } / fooYou` (Chrome) or something alone these lines, depending on where you execute it. – Gilead Jan 15 '13 at 15:41
  • Named function expressions is the recommended practice since it allows you to refer the function internally, if you need. For instance, to call the function recursively or deal with its name or properties. The major benefit, by the way, is debugging. If you use unnamed functions it's hard to debug if something happen right there, since you will get a reference to an anonymous function and not its name – Antonio Pantano Sep 25 '15 at 16:51
1

Though the complete difference is more complicated, the only difference that concerns me is when the machine creates the function object. Which in the case of declarations is before any statement is executed but after a statement body is invoked (be that the global code body or a sub-function's), and in the case of expressions is when the statement it is in gets executed. Other than that for all intents and purposes browsers treat them the same.

To help you understand, take a look at this performance test which busted an assumption I had made of internally declared functions not needing to be re-created by the machine when the outer function is invoked. Kind of a shame too as I liked writing code that way.

Jake
  • 538
  • 4
  • 12