There are two main ways to create a function.
Function declaration
function double(n) {
return n * 2;
}
Function expression
The function is created as a value and stored in a variable.
const double = function (n) {
return n * 2;
};
Both are called the same way: double(4).
The key difference: hoisting
A function declaration is available in the whole scope, even before the line where it is written. A function expression only exists after the line runs.
console.log(early(2)); // → 4
function early(n) {
return n * 2;
}
console.log(late(2)); // error on purpose: cannot access 'late' before initialization
const late = function (n) {
return n * 2;
};
Declarations let you put the main code at the top and the helper functions below. Many developers still prefer expressions assigned to const, because the order of code becomes strictly top to bottom.
Anonymous and named functions
A function without a name is anonymous: function () { ... }. You often write anonymous functions where they are used once, such as callbacks.
const numbers = [1, 2, 3];
const doubled = numbers.map(function (n) {
return n * 2;
});
console.log(doubled); // → [2, 4, 6]
Named function expressions help debugging, because the name shows in error stack traces.
IIFE (immediately invoked function expression)
A function that runs as soon as it is created. It was a popular trick for keeping variables private before modules existed.
(function () {
const secret = "only visible in here";
console.log(secret); // → only visible in here
})();
You will mostly see it in older code. Modern code uses modules and block scope for the same purpose.
Which should I write?
Both are fine. A common, simple convention:
- Declarations for named, top-level functions.
- Arrow functions (next lessons) for short callbacks and for functions stored in variables.