JavaScript: Function Declaration vs Function Expression
When you use the keyword function
to define function, there are many complex issues about name-hosting and nesting functions.
What is the difference between function declaration and function expression?
// function declaration function f () {}
and
// function expression assigned to a variable const f = function () {};
When is Function Declaration
When you have this:
function name (…) {…}
It is a function declaration if all of the following are met:
- At top-level of source code (that is, not inside any curly bracket.) or it is at top-level inside a function, it is called “Function Declaration”.
- Not on the right-hand-side of a assignment.
Function Declaration is the most common way to define a function. Example:
function f() { return 3; } console.log( f() ); // 3
Function Declaration Must be Top Level
Named function form
function name (…) {…}
is a declaration only if it is at top level of source code or top level inside a function body. When in elsewhere, its a named function expression.
const g = function f() { return 3; }; // no function declaration happens here. The f is treated as named function expression g(); // 3 // f(); // ReferenceError: f is not defined
// TypeError: undefined is not a function h(); const h = function h () {return 3;};
// ReferenceError: bb is not defined bb(); const aa = function bb () {return 3;};
// ReferenceError: bb is not defined const aa = function bb () {return 3;}; bb();
When is Function Expression
When you have this:
function name (…) {…}
or
function (…) {…}
and it is not at top-level of source code, nor at top-level inside a function, it is called “Function Expression”.
// function expression, applied on the spot console.log( (function () { return 3; })() ); // 3
// function expression with one parameter, applied on the spot console.log( (function (x) { return x; })(4) ); // 4
You can assign a function to a variable. In effect, giving the function a name.
const g = function () { return 3; }; console.log(g()); // 3
Function Declaration → Hoisting Name and Value
Function declaration will implicitly move the function name and definition to the top.
Function expression assigned to variable will only hoist the name, not the definition.
Compare:
f(); // returns 3 function f () {return 3;}
// error: Uncaught ReferenceError: Cannot access 'f' before initialization g(); const g = function () {return 3;};
[see var Declaration Order]
Tip: never use the keyword 「function」
You can always define function by Arrow Function. Or use keyword class [see Class] to define a class.
Advantage:
- No complexities of name hoisting [see var Declaration Order]
- Can move function anywhere, including inside
if
statement or any block construct{…}
. The name will be local to that code block.