Function Declarations, Expressions, and Arrow Functions
Three syntaxes for creating a function value, differing in hoisting behavior and how they handle this.
function name() {} / const name = function () {} / const name = () => {}
Purpose
JavaScript has three ways to write a function value, differing mainly in hoisting and in how each
handles this (covered in depth in the Intermediate tier).
Syntax
function add(a, b) {
return a + b;
}
const subtract = function (a, b) {
return a - b;
};
const multiply = (a, b) => a * b;
Behavior notes
- A function declaration is hoisted — the whole function is available before its own line executes, anywhere in its enclosing scope.
- A function expression (assigned to a binding) is only callable after that line executes, like
any other
const/letvalue. - An arrow function is always an expression, never a declaration. It cannot be used as a
constructor (
new arrowFn()throws), and it does not have its ownthis,arguments, orsuper— it uses the enclosing scope’s. - An arrow function with a single expression body (no
{ }) implicitly returns that expression’s value; one with a block body ({ }) needs an explicitreturn.
Common mistakes
- Calling a function expression before the line that defines it, expecting declaration-style
hoisting — this throws a
ReferenceError(orTypeErrorif the binding exists but isn’t yet assigned). - Using an arrow function where a method needing its own
thiswas intended — this becomes relevant once objects and classes are introduced in the Intermediate tier.
Runtime notes
All three forms are core ECMAScript (arrow functions since ES2015) with identical behavior across browsers and Node.