JavaScript Function Definitions
Learn different ways to define functions in JavaScript and understand when to use each approach
45 min•By Priygop Team•Last updated: Feb 2026
Function Declaration Methods
JavaScript provides multiple ways to define functions, each with different characteristics, hoisting behavior, and use cases. Understanding these differences is crucial for writing clean, maintainable code.
Function Definition Types
- Function Declaration: Traditional function definition
- Function Expression: Function assigned to variable
- Arrow Function: Modern concise syntax (ES6+)
- Generator Function: Functions that can pause execution
- Async Function: Functions that return promises
Function Declaration Examples
Example
// 1. Function Declaration (hoisted)
function greet(name) {
return `Hello, ${name}!`;
}
// 2. Function Expression
const greetUser = function(name) {
return `Hello, ${name}!`;
};
// 3. Arrow Function (ES6+)
const greetArrow = (name) => `Hello, ${name}!`;
// 4. Generator Function
function* numberGenerator() {
yield 1;
yield 2;
yield 3;
}
// 5. Async Function
async function fetchUser(id) {
const response = await fetch(`/api/users/${id}`);
return response.json();
}
// Hoisting demonstration
console.log(greet("John")); // Works - function is hoisted
// console.log(greetUser("Jane")); // Error - not hoisted
// Function expressions with different syntax
const add = function(a, b) {
return a + b;
};
const multiply = (a, b) => a * b;
const divide = (a, b) => {
if (b === 0) {
throw new Error("Division by zero");
}
return a / b;
};
// Immediately Invoked Function Expression (IIFE)
(function() {
console.log("This function runs immediately");
})();
// Modern function patterns (2025)
// Function with default parameters
function createUser(name, email, role = "user", isActive = true) {
return {
name,
email,
role,
isActive,
createdAt: new Date()
};
}
// Function with rest parameters
function sum(...numbers) {
return numbers.reduce((total, num) => total + num, 0);
}
// Function with destructuring
function processUser({ name, email, age = 0 }) {
return `Processing ${name} (${email}) - Age: ${age}`;
}
// Arrow functions with different bodies
const square = x => x * x;
const cube = x => x * x * x;
const processArray = arr => {
const doubled = arr.map(x => x * 2);
const filtered = doubled.filter(x => x > 10);
return filtered.reduce((sum, x) => sum + x, 0);
};
// Generator function example
function* fibonacci() {
let [prev, curr] = [0, 1];
while (true) {
yield curr;
[prev, curr] = [curr, prev + curr];
}
}
// Async function with error handling
async function fetchData(url) {
try {
const response = await fetch(url);
if (!response.ok) {
throw new Error(`HTTP error! status: ${response.status}`);
}
return await response.json();
} catch (error) {
console.error('Fetch error:', error.message);
return null;
}
}Function Parameters & Arguments
Example
// Function parameters and arguments
// Default parameters
function greet(name = "Guest", greeting = "Hello") {
return `${greeting}, ${name}!`;
}
console.log(greet()); // "Hello, Guest!"
console.log(greet("John")); // "Hello, John!"
console.log(greet("Jane", "Hi")); // "Hi, Jane!"
// Rest parameters
function calculateSum(...numbers) {
return numbers.reduce((sum, num) => sum + num, 0);
}
console.log(calculateSum(1, 2, 3, 4, 5)); // 15
console.log(calculateSum(10, 20)); // 30
// Destructuring parameters
function processUser({ name, email, age = 0, preferences = {} }) {
return {
id: Date.now(),
name,
email,
age,
preferences,
processedAt: new Date()
};
}
const user = {
name: "John Doe",
email: "john@example.com",
age: 30,
preferences: { theme: "dark" }
};
console.log(processUser(user));
// Arguments object (legacy)
function legacyFunction() {
console.log("Number of arguments:", arguments.length);
console.log("Arguments:", Array.from(arguments));
}
legacyFunction(1, 2, 3, "hello");
// parameter validation
function validateAndProcess(data, options = {}) {
// Validate required parameters
if (!data || typeof data !== 'object') {
throw new Error('Data must be a valid object');
}
if (!data.name || typeof data.name !== 'string') {
throw new Error('Name is required and must be a string');
}
// Process with options
const { validateEmail = true, strictMode = false } = options;
if (validateEmail && data.email) {
const emailRegex = /^[^s@]+@[^s@]+.[^s@]+$/;
if (!emailRegex.test(data.email)) {
throw new Error('Invalid email format');
}
}
if (strictMode && data.age < 0) {
throw new Error('Age cannot be negative');
}
return {
...data,
validated: true,
processedAt: new Date()
};
}
// Function overloading simulation
function processData(data, type = 'default') {
switch (type) {
case 'user':
return processUserData(data);
case 'product':
return processProductData(data);
case 'order':
return processOrderData(data);
default:
return processDefaultData(data);
}
}
function processUserData(data) {
return { ...data, type: 'user', processed: true };
}
function processProductData(data) {
return { ...data, type: 'product', processed: true };
}
function processOrderData(data) {
return { ...data, type: 'order', processed: true };
}
function processDefaultData(data) {
return { ...data, type: 'default', processed: true };
}Practice Exercise: Function Definitions
Example
// Exercise: Build a Function Library
class FunctionLibrary {
constructor() {
this.functions = new Map();
}
// Register a function
register(name, func, description = '') {
if (typeof func !== 'function') {
throw new Error('Second argument must be a function');
}
this.functions.set(name, {
func,
description,
registeredAt: new Date()
});
console.log(`Function '${name}' registered successfully`);
}
// Execute a registered function
execute(name, ...args) {
const funcData = this.functions.get(name);
if (!funcData) {
throw new Error(`Function '${name}' not found`);
}
try {
const result = funcData.func(...args);
console.log(`Function '${name}' executed successfully`);
return result;
} catch (error) {
console.error(`Error executing function '${name}':`, error.message);
throw error;
}
}
// List all registered functions
list() {
return Array.from(this.functions.entries()).map(([name, data]) => ({
name,
description: data.description,
registeredAt: data.registeredAt
}));
}
// Remove a function
remove(name) {
if (this.functions.delete(name)) {
console.log(`Function '${name}' removed successfully`);
} else {
console.log(`Function '${name}' not found`);
}
}
}
// Exercise: Build a Calculator with Functions
class FunctionCalculator {
constructor() {
this.operations = new Map();
this.history = [];
this.initializeOperations();
}
initializeOperations() {
// Basic arithmetic
this.operations.set('add', (a, b) => a + b);
this.operations.set('subtract', (a, b) => a - b);
this.operations.set('multiply', (a, b) => a * b);
this.operations.set('divide', (a, b) => {
if (b === 0) throw new Error('Division by zero');
return a / b;
});
// Advanced operations
this.operations.set('power', (a, b) => Math.pow(a, b));
this.operations.set('sqrt', (a) => {
if (a < 0) throw new Error('Cannot calculate square root of negative number');
return Math.sqrt(a);
});
this.operations.set('log', (a) => Math.log(a));
// Statistical operations
this.operations.set('average', (...numbers) => {
if (numbers.length === 0) throw new Error('No numbers provided');
return numbers.reduce((sum, num) => sum + num, 0) / numbers.length;
});
this.operations.set('max', (...numbers) => Math.max(...numbers));
this.operations.set('min', (...numbers) => Math.min(...numbers));
}
calculate(operation, ...args) {
const func = this.operations.get(operation);
if (!func) {
throw new Error(`Unknown operation: ${operation}`);
}
try {
const result = func(...args);
this.history.push({
operation,
args,
result,
timestamp: new Date()
});
return result;
} catch (error) {
console.error(`Calculation error: ${error.message}`);
throw error;
}
}
addCustomOperation(name, func) {
if (typeof func !== 'function') {
throw new Error('Second argument must be a function');
}
this.operations.set(name, func);
console.log(`Custom operation '${name}' added successfully`);
}
getHistory() {
return this.history;
}
clearHistory() {
this.history = [];
}
}
// Test the exercises
const lib = new FunctionLibrary();
// Register some functions
lib.register('greet', (name) => `Hello, ${name}!`, 'Greets a person');
lib.register('add', (a, b) => a + b, 'Adds two numbers');
lib.register('multiply', (a, b) => a * b, 'Multiplies two numbers');
// Execute functions
console.log(lib.execute('greet', 'John')); // "Hello, John!"
console.log(lib.execute('add', 5, 3)); // 8
// List registered functions
console.log(lib.list());
const calc = new FunctionCalculator();
// Basic calculations
console.log(calc.calculate('add', 10, 5)); // 15
console.log(calc.calculate('multiply', 4, 3)); // 12
console.log(calc.calculate('power', 2, 8)); // 256
// Statistical calculations
console.log(calc.calculate('average', 1, 2, 3, 4, 5)); // 3
console.log(calc.calculate('max', 10, 5, 20, 15)); // 20
// Add custom operation
calc.addCustomOperation('factorial', (n) => {
if (n < 0) throw new Error('Factorial not defined for negative numbers');
if (n === 0 || n === 1) return 1;
return n * calc.calculate('factorial', n - 1);
});
console.log(calc.calculate('factorial', 5)); // 120