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.

Answer from Khon Lieu on Stack Overflow
Top answer
1 of 5
430

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.

2 of 5
114

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

Douglas Crockford recommends to use function expression in his «JavaScript: The Good Parts» book 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.

Discussions

Why is it called a function expression and not a function declaration?
I am beginning to learn React, and now I am circling back to some of the more basic concepts in JavaScript. I have learned the difference between function expressions and function declarations, but... More on stackoverflow.com
🌐 stackoverflow.com
Function expressions vs function declarations: return value
In a Udacity lesson the difference between function expressions and declarations is explained as follows: A function declaration defines a function and does not require a variable to be assigne... More on stackoverflow.com
🌐 stackoverflow.com
Function Declaration vs Expression
You need function declarations if you want to follow the pattern where you put helper functions at the end of a file but call them earlier in the file. That’s sort of an antiquated non-JS pattern at this point though. Lately, I have gravitated towards declarations for top-level functions, but arrow expressions for in-line callbacks and such. It’s all just style choices though. More on reddit.com
🌐 r/learnjavascript
9
4
October 21, 2023
oop - Know JavaScript Function Expression vs Function Declaration, but what is this? Named Function Expression? - Stack Overflow
You probably haven't read these ... and stackoverflow.com/questions/336859/… ... I don't believe this question is a dupe since it is asking specifically about the case where the variable name and function name are different (even though it is answered by one of the answered on one of the other questions). ... Its not a duplicate. The questions that have been added to "Possible Duplicate" are for differences in declaration and expression... More on stackoverflow.com
🌐 stackoverflow.com
Top answer
1 of 1
3

The comments in the MDN page are very misleading. (MDN is a collaboratively-edited reference. It's normally excellent. Sometimes it falls a bit short of that.)

From above example,

1) Is function world an expression or declaration?

2) Is function c an expression or declaration?

Until ES2015 (aka "ES6"), they were both unspecified behavior because they were function declarations within a control-flow block. The specification didn't define how they should be handled, but handling them was an "allowable extension" under the spec (blech) and some engines did support them. Unfortunately, different engines supported them by doing different things.

As of ES2015, though, the spec takes them on: They're still function declarations, but how they're interpreted varies depending on whether...

  • ...the code is in strict mode (in which the behavior is rational and straightfoward),
  • ...the code is in loose mode on a browser-hosted JavaScript engine that implements the optional legacy behavior described by Annex B.3.3 and Annex B.3.4 of the spec (confusing, and there are only a couple of scenarios that are safe cross-browser),
  • ...or whether the code is in loose mode on a non-browser JavaScript engine, which in theory isn't supposed to implement Annex B (but that doesn't stop them).

Since in loose mode you can't be sure whether the JavaScript engine is going to implement the Annex B behavior or the non-Annex B behavior, the only reasonable choices are:

  • Use strict mode, or
  • Don't use block-level function declarations.

If you use strict mode (whether on a browser or not), the behavior is quite straightforward: The declaration is hoisted to the top of its block and is block-scoped (like let and const are). The identifier created by the declaration is writable, and so it's as though the declaration were converted to a function expression assigned to a let variable at the top of the block. Let's take the world example but add some to it.

This:

"use strict";
// ...
function example() {
    if (x) {
        console.log("testing:");
        console.log("1:", typeof world);
        function world() {}
        console.log("2:", typeof world);
    }
    console.log("3":, typeof world);
    console.log("4:", world === undefined);
}

...effectively becomes this:

"use strict";
// ...
function example() {
    if (x) {
        let world = function world() {};
        console.log("testing:");             // testing:
        console.log("1:", typeof world);     // 1: function
        console.log("2:", typeof world);     // 2: function
    }
    console.log("3:", typeof world);        // 3: undefined
    console.log("4:", world === undefined); // ReferenceError: `world` is not defined
}

Notice how the declaraton was hoisted to the top of the block, and is block-scoped.

Outside of strict mode, again, it depends, but the non-legacy version is just like strict mode but with var instead of let.

So: this:

This:

// NOT in strict mode
function example() {
    if (x) {
        console.log("testing:");
        console.log("1:", typeof world);
        function world() {}
        console.log("2:", typeof world);
    }
    console.log("3":, typeof world);
    console.log("4:", world === undefined);
}

...effectively becomes this:

// NOT in strict mode
function example() {
    var world;
    if (x) {
        world = function world() {};
        console.log("testing:");             // testing: (if executed)
        console.log("1:", typeof world);     // 1: function (if executed)
        console.log("2:", typeof world);     // 2: function (if executed) 
    }
    console.log("3:", typeof world);        // 3: function if `x` is truthy, undefined if `x` is falsy
    console.log("4:", world === undefined); // 4: false if `x` is truthy, true if `x` is falsy
}
Top answer
1 of 2
2

Interesting question. Wording can have soft boundaries, which is partly what causes this confusion.

First, some rough definitions:

  • Expression: I think this is best thought of with an example. 2 * 2 is an expression, because you can continue doing other operations on it, like 2 * 2 - 3. if (...) on the other hand is not an expression in javascript, it does not resolve into a value in which you can do further operations on. It's invalid to do if (...) {...} / 2. This "definition" has some holes, but should be good enough for the purposes of this answer.
  • Declaration: A declaration is just declaring that you're going to use a certain variable name. So, in your example with const foo = 5, It's the const foo part that actually declares, the = 5 is just initializing the declaration.

With that in mind, lets consider two examples of functions, and see how this terminology plays into these examples:

  1. const g = function() {}

There is a declaration going on here, the const g. We also see that there's a function being created and assigned to g. We're doing something with the result of function() {} (we're assigning it to something), which means javascript will interpret this as a function expression.

  1. function f() {}

We're not using this function as an expression (we're not doing any additional operations with it after we create it), so javascript will actually treat this different from our first example. It's going to declare f in the local namespace, and it's going to apply function hoisting. If you simply added a + before function f() {}, then you would cause javascript to interpret this as an expression instead, and these features will be disabled. You can try it in the dev tools - put in +function f(){} or const g = function f(){}, and f will remain undefined.

The fact that javascript treats the function keyword differently in different contexts is at the heart of this language choice. You can almost think of the "function" keyword as having two different meaning, and the chosen meaning depends on the context. Any time the function is used in an expression context or when it's unnamed, then it takes on the "expression" form, and we call it a "function expression". Otherwise, it takes on the alternative form that contains some extra features, like declaring the function name as a local variable. This is probably why we've adopted to call this alternative form a function declaration. However, like the OP rightly pointed out, even with const f = function() {}, a declaration is still happening, it's just not happening by the function keyword.

Footnote: With examples like +function f() {}, f won't be defined in the same scope as g, but it does get defined inside the body of f. In other words, any named function expression declares its name within its own body.

2 of 2
0

Then why is this called a function expression?:

Assigning a variable a value, is in fact, an expression. In your example foo = 5, that is an expression. You are also declaring foo, but its still an expression.

Similarly, the other example const bar = function() {} is called a function expression to differentiate between a function declaration, and a function expression.

Function expression

const bar = function() {
    // Some code
};

vs Function declaration

function foo() {
    // Some code
};
🌐
freeCodeCamp
freecodecamp.org › news › function-declaration-vs-function-expression
Function Declaration vs Function Expression
April 26, 2023 - As you see here, we have the function keyword without a name for the function. This makes it an expression, which you have to assign to a variable (as we have done to generateIntro here). Note: you can use const, let or var to declare the variable.
Top answer
1 of 5
4

To understand what this really is about, we need to dig into the JavaScript grammar:

In ECMAScript a script consists of Statements and Declarations. A Statement can be (amongst others) an ExpressionStatement. Note that ExpressionStatement is explicitly defined as:

ExpressionStatement[Yield, Await]:

[lookahead ∉ { {, function, async [no LineTerminator here] function, class, let [ }]

Expression[+In, ?Yield, ?Await];

This looks really cumbersome, but what it says is that an ExpressionStatement cannot possibly start with the keyword function. So if you just write:

function a() {}

This can never be interpreted as an expression although in other circumstances like

const a = function a() {}

it is an expression. (The right hand side of an assignment operation always must be an expression.)

Now, only expressions evaluate a value, statements do not. This is all the text you quote is saying in a hard to understand way.

A function declaration defines a function and does not require a variable to be assigned to it:

True but redundant. A declaration cannot occur at the right hand-side of an assignment.

It simply declares a function, and doesn't itself return a value ...

Yeah, statements do not evaluate to ("return") a value.

On the other hand, a function expression does return a value.

Sure, like any expression.


See https://www.ecma-international.org/ecma-262/8.0/#prod-StatementList

2 of 5
2

On the other hand, a function expression does return a value.

This is confusing

Yes indeed. What they actually meant was a function expression evaluates to a (function) value - in contrast to a declaration, which is not an expression but a statement and doesn't evaluate to anything. It has nothing do with the value that the function might return from a call.

🌐
Reddit
reddit.com › r/learnjavascript › function declaration vs expression
r/learnjavascript on Reddit: Function Declaration vs Expression
October 21, 2023 -

So I understand the difference between the two, but is it a case where I should've use a certain one instead of the other ? Or could I just use function expression for everything?

Top answer
1 of 5
5
You need function declarations if you want to follow the pattern where you put helper functions at the end of a file but call them earlier in the file. That’s sort of an antiquated non-JS pattern at this point though. Lately, I have gravitated towards declarations for top-level functions, but arrow expressions for in-line callbacks and such. It’s all just style choices though.
2 of 5
2
Any time you use a function as you would a variable, e.g. assigning it to another variable, passing it as a callback, returning it from a parent function, using the IIFE pattern, these are all function expressions. The only time it's a function declaration is when you begin a statement with the function keyword. Function expressions: setTimeout(function () {}); (function () {})(); const f = function () {}; Function declaration: function f() {} There are a couple of minor differences: assigning a function to a const means it can't be redeclared later, so it can act as a safeguard in that context. This has never been a problem for me in the real world, however. The one big difference is that you can't use an arrow function as a function declaration, only as a function expression. My personal opinion is that, unless you have good reason to deviate, if you're simply... well... declaring a function, use a function declaration. For me, seeing the function keyword at the start of the line makes it clear that you're simply defining a function and not trying to do anything else with it, like immediately invoking it. Many people seem to prefer using const f = ..., presumably because it allows them to use arrow notation, and some people really like arrow notation.
Find elsewhere
🌐
MDN Web Docs
developer.mozilla.org › en-US › docs › Web › JavaScript › Reference › Operators › function
function expression - JavaScript - MDN Web Docs - Mozilla
If a function expression is named, the name property of the function is set to that name, instead of the implicit name inferred from syntax (such as the variable the function is assigned to). Unlike declarations, the name of the function expressions is read-only.
🌐
SitePoint
sitepoint.com › blog › javascript › when to use a function expression vs. function declaration
When to Use a Function Expression vs. Function Declaration — SitePoint
November 7, 2024 - This means that you can call the function before it is defined. ... Function expressions are when you create a function and assign it to a variable. The function is anonymous, which means it doesn’t have a name.
🌐
freeCodeCamp
freecodecamp.org › news › when-to-use-a-function-declarations-vs-a-function-expression-70f15152a0a0
When to use a function declaration vs. a function expression
April 19, 2019 - If that callback is a function expression, it will not be available outside of the function that uses it: ... In short, use function declarations when you want to create a function on the global scope and make it available throughout your code.
🌐
Go Make Things
gomakethings.com › function-expressions-vs-function-declarations
Function expressions vs. function declarations | Go Make Things
This allows you to call a function before you declare. /** * This works! */ function add(num1, num2) { return num1 + num2; } add(3, 3); // returns 6 /** * This does, too! */ substract(7, 4); // returns 3 function subtract(num1, num2) { return num1 - num2; } Function expressions, however, do not hoist.
🌐
DEV Community
dev.to › catherineisonline › function-declarations-function-expressions-2o5k
Function declaration vs expression - DEV Community
August 13, 2024 - We declare a function with a Function constructor and give it a name ... If you create a function with no name, it becomes a function expression.
🌐
JavaScript.info
javascript.info › tutorial › the javascript language › javascript fundamentals
Function expressions
A Function Expression is created when the execution reaches it and is usable only from that moment. Once the execution flow passes to the right side of the assignment let sum = function…
🌐
Stack Overflow
stackoverflow.com › questions › 55465969 › declare-the-function-vs-declaration
Declare the Function vs Declaration
Both can be called in the usual way. The results are almost identical, except that the function declaration is hoisted and the const declaration is not.