Comprehensive Guide to JavaScript Functions: Declarations, Expressions, and Advanced Patterns
In JavaScript, a function encapsulates reusable logic and executes when invoked. Every function returns a value—explicitly via return, or implicitly as undefined.
Function Nature
Functions are objects created by the built-in Function constructor. Their prototype chain is:
Object.prototype ← Function.prototype ← [Function Instance]
Thus, all functions inherit from Function.prototype and ultimately Object.prototype.
Function Declaration
Declared with the function keyword, these are hoisted—available before their definition in code:
function add(x, y) {
return x + y;
}
- Function names follow variable naming rules (often verbs).
- Parameters (
x,y) act as local variables initialized with passed arguments. - Use
add.lengthto get the number of expected parameters.
For more than three parameters, prefer an object:
function compute({ val1, val2, val3, val4 }) {
return val1 + val2 + val3 + val4;
}
Default Parameters
Assign defaults directly in the parameter list:
function multiply(a, b = 2) {
return a * b;
}
Default expressions can reference earlier parameters:
function createPair(x = 1, y = x * 2) {
return [x, y];
}
Default parameters have their own scope between outer and function scopes.
Rest Parameters
Capture extra arguments as an array using ...:
function logFirstAndRest(first, ...others) {
console.log(first, others); // others is a true Array
}
logFirstAndRest('a', 'b', 'c'); // 'a' ['b', 'c']
Rest parameters must be last and only one is allowed.
Function Expression
Assign a function to a variable:
const subtract = function(a, b) {
return a - b;
};
The function name (if provided) is optional and not accessible outside the expression.
Anonymous Functions
Functions without names, commonly used in callbacks or IIFEs.
Immediately Invoked Function Expression (IIFE)
Execute a function right after declaration:
(function(msg) {
console.log(msg);
})('Hello!');
Arrow Functions (ES6)
Concise syntax with lexical this binding:
const square = x => x * x;
const greet = (name, title) => `Hi ${title} ${name}`;
Arrow functions:
- Do not have their own
this,arguments, orsuper. - Cannot be used as constructors (
newthrows a error). - Avoid in object methods, event handlers, or any context requiring dynamic
this.
Callback Functions
A function passed as a argument to be executed later:
function fetchData(callback) {
setTimeout(() => callback('Data ready'), 1000);
}
fetchData(result => console.log(result));
Common in asynchronous APIs like setTimeout and setInterval.
Built-in Global Functions
Available globally (as window methods in browsers):
setTimeout(fn, delay): Delayed execution.setInterval(fn, interval): Repeated execution.encodeURI(url): Encodes URL-safe characters (preserves/,?, etc.).encodeURIComponent(str): Encodes all special characters (use for query parameters).decodeURI/decodeURIComponent: Reverse encoding.
Example:
const encoded = encodeURIComponent('https://test.com/?q=hello world');
// Result: 'https%3A%2F%2Ftest.com%2F%3Fq%3Dhello%20world'
Private Functions
Nested functions are scoped to their parent:
function process(value) {
function validate(v) {
return v > 0;
}
return validate(value) ? value * 2 : 0;
}
// validate() is inaccessible outside process()
Simulating Function Overloading
JavaScript doesn’t support true overloading (duplicate names overwrite). Instead, inspect arguments:
function handleInput(...args) {
if (args.length === 1 && typeof args[0] === 'string') {
console.log('String input:', args[0]);
} else if (args.length === 2 && !isNaN(args[0]) && !isNaN(args[1])) {
console.log('Numeric inputs:', args[0] + args[1]);
}
}
handleInput('text'); // String input
handleInput(3, 4); // Numeric inputs: 7
Alternatively, use parameter destructuring with defaults for flexible interfaces.
Factory Functions
Return new objects without using new:
function createUser(name, age) {
return {
name,
age,
introduce() {
console.log(`I'm ${this.name}`);
}
};
}
const user1 = createUser('Alice', 30);
All instances are plain objects (typeof user1 === 'object'), lacking constructor identity.
High-Order Functions
Functions that accept or return other functions:
function withLogging(fn) {
return function(...args) {
console.log('Calling with', args);
return fn(...args);
};
}
const loggedAdd = withLogging((a, b) => a + b);
loggedAdd(2, 3); // Logs args, returns 5
Built-in examples: Array.map, Array.filter, setTimeout.
Implicit Parameters
Every function has access to:
this: Context object (varies by invocation mode).arguments: Array-like object of all passed arguments (not available in arrow functions).
Convert arguments to a real array:
function toArray() {
return Array.from(arguments);
}
Or use rest parameters instead for cleaner code.