Explain the differences on the usage of `foo` between `function foo() {}` and `var foo = function() {}` in JavaScript
TL;DR
function foo() {}
a function declaration while the var foo = function() {}
is a function expression. The key difference is that function declarations have its body hoisted but the bodies of function expressions are not (they have the same hoisting behavior as var
-declared variables).
If you try to invoke a function expression before it is declared, you will get an Uncaught TypeError: XXX is not a function
error.
Function declarations can be called in the enclosing scope even before they are declared.
foo(); // 'FOOOOO'function foo() {console.log('FOOOOO');}
Function expressions if called before they are declared will result in an error.
foo(); // Uncaught TypeError: foo is not a functionvar foo = function () {console.log('FOOOOO');};
Another key difference is in the scope of the function name. Function expressions can be named by defining it after the function
and before the parenthesis. However when using named function expressions, the function name is only accessible within the function itself. Trying to access it outside will result in an error or undefined
.
const myFunc = function namedFunc() {console.log(namedFunc); // Works};console.log(namedFunc); // undefined
Note: The examples uses var
due to legacy reasons. Function expressions can be defined using let
and const
and the key difference is in the hoisting behavior of those keywords.
Function declarations
A function declaration is a statement that defines a function with a name. It is typically used to declare a function that can be called multiple times throughout the enclosing scope.
function foo() {console.log('FOOOOO');}
Function expressions
A function expression is an expression that defines a function and assigns it to a variable. It is often used when a function is needed only once or in a specific context.
var foo = function () {console.log('FOOOOO');};
Note: The examples uses var
due to legacy reasons. Function expressions can be defined using let
and const
and the key difference is in the hoisting behavior of those keywords.
Key differences
Hoisting
The key difference is that function declarations have its body hoisted but the bodies of function expressions are not (they have the same hoisting behavior as var
-declared variables). For more explanation on hoisting, refer to the quiz question on hoisting. If you try to invoke a function expression before it is defined, you will get an Uncaught TypeError: XXX is not a function
error.
Function declarations:
foo(); // 'FOOOOO'function foo() {console.log('FOOOOO');}
Function expressions:
foo(); // Uncaught TypeError: foo is not a functionvar foo = function () {console.log('FOOOOO');};
Name scope
Function expressions can be named by defining it after the function
and before the parenthesis. However when using named function expressions, the function name is only accessible within the function itself. Trying to access it outside will result in undefined
and calling it will result in an error.
const myFunc = function namedFunc() {console.log(namedFunc); // Works};console.log(namedFunc); // undefined
When to use each
- Function declarations:
- When you want to create a function on the global scope and make it available throughout the enclosing scope.
- If a function is reusable and needs to be called multiple times.
- Function expressions:
- If a function is only needed once or in a specific context.
- Use to limit the function availability to subsequent code and keep the enclosing scope clean.
In general, it's preferable to use function declarations to avoid the mental overhead of determining if a function can be called. The practical usages of function expressions is quite rare.