3

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 it still puzzles me as to why a function expression is not called a function declaration.

If this is a variable declaration:

const foo = 5;

Then why is this called a function expression?:

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

In the second example, isn't "const bar" being declared? Why are function expressions and function declarations named the way they are? Why aren't function expressions called function declarations and vice versa?

neovr
  • 147
  • 1
  • 2
  • 10
  • 1
    There are some resources on the web for this, including https://kangax.github.io/nfe/#expr-vs-decl. – Cat Nov 17 '20 at 05:17
  • The `const bar` initialization is a function expression because *anything* that initializes a declared variable like that is an expression of one form or another. – Pointy Nov 17 '20 at 05:20
  • `const foo` is the variable declaration `5` is an expression, not a declaration. Consider `const foo = 1 + 1`. It is obvious that `1 + 1` is an expression that needs to be evaluated – slebetman Nov 17 '20 at 05:23
  • Related: [var functionName = function() {} vs function functionName() {}](https://stackoverflow.com/q/336859/4642212). – Sebastian Simon Nov 17 '20 at 05:35
  • The first code block is a _StatementList_ → _StatementListItem_ → _Declaration_ → _LexicalDeclaration_ → _LetOrConst BindingList_ → `const` _LexicalBinding_ → `const` _BindingIdentifier Initializer_ → `const` _Identifier_ `=` _AssignmentExpression_ → [20 steps skipped] → `const foo =` _PrimaryExpression_ → `const foo =` _Literal_ → `const foo =` _NumericLiteral_ → [4 steps skipped] → `const foo = 5`. The second block diverges at _Literal_ → _FunctionExpression_ → etc. See [the spec](https://tc39.es/ecma262). _FunctionDeclaration_ comes from _Declaration_ → _HoistableDeclaration_. – Sebastian Simon Nov 17 '20 at 06:02

2 Answers2

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.

Sebastian Simon
  • 18,263
  • 7
  • 55
  • 75
Scotty Jamison
  • 10,498
  • 2
  • 24
  • 30
  • Very minor nitpick: a few expressions still depend on context; you cannot arbitrarily combine expressions. For example: `await x` is an expression, but `() => await x` is not valid because `await` isn’t used directly within an `async` function. Also, the _whole_ `const foo = 5` is a declaration. `const foo = 5` comes from `const` _Identifier_ `=` _AssignmentExpression_, which is derived from `const` _BindingIdentifier Initializer_, derived from _LetOrConst LexicalBinding_, which comes from [_LexicalDeclaration_](https://tc39.es/ecma262/#prod-LexicalDeclaration). `const foo` is a syntax error. – Sebastian Simon Nov 17 '20 at 08:30
  • 1
    Thanks @user4642212 - I incorporated your feedback into the answer - I was hoping people would find places where I was a little off in my explanations. And I guess you're right, the whole `const foo = 5` is both a declaration *and* a default initialization. It's probably unfair for me to try to subdivide which part of that statement is declaring "foo" as a constant and which part is default initializing it, as they're both needed for it to work - but I'll leave it in anyways as it makes the answer easier to understand (I did clarified my wording to sound less strong about it). – Scotty Jamison Nov 17 '20 at 08:51
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
};
element11
  • 4,218
  • 2
  • 16
  • 22