Web Development / JavaScript

JavaScript Functions - Complete Guide

Master JavaScript functions including function declarations, expressions, arrow functions, parameters, and closures. Build a practical calculator example.

Intermediate
⏱️ 12 minutes📚 Prerequisites: javascript-basics

Introduction

What You'll Learn

  • Function declarations and expressions
  • Arrow functions (ES6)
  • Parameters and arguments
  • Return values and early returns
  • Function scope and closures
  • Higher-order functions
  • Building a practical calculator application

Why This Topic is Important

Functions are the building blocks of JavaScript. They allow you to organize code into reusable blocks, making your programs more modular, readable, and maintainable. Understanding functions is essential for any JavaScript developer, as they're used everywhere - from simple calculations to complex application logic.

Real-World Applications

  • Creating reusable code blocks
  • Event handlers in web applications
  • API request functions
  • Data transformation and processing
  • Building interactive user interfaces
  • Creating utility functions
  • Implementing algorithms and data structures

Learning Objectives

  • Understand different ways to define functions
  • Master function parameters and return values
  • Learn arrow function syntax and when to use it
  • Understand function scope and closures
  • Create practical, reusable functions
  • Build a complete calculator application

What are Functions?

A function is a block of code designed to perform a specific task. Functions allow you to organize code into reusable pieces, avoid repetition, and make your code more maintainable. When you call (invoke) a function, it executes the code inside it.

Think of a function as a recipe: you define it once with ingredients (parameters), and you can use it multiple times to cook (execute) the same dish (get the result).

📝 Note

Functions in JavaScript are first-class citizens, meaning they can be assigned to variables, passed as arguments, and returned from other functions.

Function Declaration

The most common way to define a function is using a function declaration. Function declarations are hoisted, meaning they can be called before they're defined in the code.

JAVASCRIPT
// Function declaration
function greet(name) {
  return `Hello, ${name}!`;
}

// Calling the function
console.log(greet('Alice')); // Output: Hello, Alice!
console.log(greet('Bob'));   // Output: Hello, Bob!

Function declarations start with the `function` keyword, followed by the function name, parameters in parentheses, and the function body in curly braces.

JAVASCRIPT
// Function with multiple parameters
function calculateArea(width, height) {
  return width * height;
}

const area = calculateArea(5, 10);
console.log(area); // Output: 50

Functions can accept multiple parameters. The `return` statement sends a value back to the caller.

Function Expression

A function expression assigns a function to a variable. Unlike function declarations, function expressions are not hoisted and cannot be called before they're defined.

JAVASCRIPT
// Function expression
const greet = function(name) {
  return `Hello, ${name}!`;
};

console.log(greet('Charlie')); // Output: Hello, Charlie!

// Anonymous function expression
const multiply = function(a, b) {
  return a * b;
};

console.log(multiply(3, 4)); // Output: 12

Function expressions are useful when you want to assign functions to variables or pass them as arguments.

Arrow Functions (ES6)

Arrow functions provide a shorter syntax for writing functions. They're especially useful for short, simple functions and are commonly used in modern JavaScript.

JAVASCRIPT
// Arrow function syntax
const greet = (name) => {
  return `Hello, ${name}!`;
};

// Shorter syntax (single expression)
const greet = (name) => `Hello, ${name}!`;

// Even shorter (single parameter, no parentheses needed)
const greet = name => `Hello, ${name}!`;

// Multiple parameters
const add = (a, b) => a + b;

// No parameters
const sayHello = () => 'Hello, World!';

console.log(greet('David')); // Output: Hello, David!
console.log(add(5, 3));       // Output: 8
console.log(sayHello());      // Output: Hello, World!

Arrow functions use `=>` syntax. If the function body is a single expression, you can omit the curly braces and return statement.

💡 Tip

Arrow functions don't have their own `this` binding, which makes them perfect for callbacks and event handlers where you want to preserve the outer scope's `this`.

Parameters and Arguments

Parameters are the variables listed in the function definition. Arguments are the actual values passed to the function when it's called.

JAVASCRIPT
// Parameters with default values
function greet(name = 'Guest', greeting = 'Hello') {
  return `${greeting}, ${name}!`;
}

console.log(greet());              // Output: Hello, Guest!
console.log(greet('Alice'));       // Output: Hello, Alice!
console.log(greet('Bob', 'Hi'));    // Output: Hi, Bob!

// Rest parameters (collect remaining arguments)
function sum(...numbers) {
  return numbers.reduce((total, num) => total + num, 0);
}

console.log(sum(1, 2, 3));        // Output: 6
console.log(sum(1, 2, 3, 4, 5));  // Output: 15

Default parameters allow you to provide fallback values. Rest parameters (`...`) collect multiple arguments into an array.

Return Values

Functions can return values using the `return` statement. If no return is specified, the function returns `undefined`.

JAVASCRIPT
// Function with return value
function multiply(a, b) {
  return a * b;
}

const result = multiply(4, 5);
console.log(result); // Output: 20

// Function without return (returns undefined)
function logMessage(message) {
  console.log(message);
  // No return statement
}

const value = logMessage('Hello');
console.log(value); // Output: undefined

// Early return
function checkAge(age) {
  if (age < 18) {
    return 'Minor';
  }
  return 'Adult';
}

console.log(checkAge(15)); // Output: Minor
console.log(checkAge(25)); // Output: Adult

The `return` statement exits the function and sends a value back. You can use early returns to exit functions conditionally.

Function Scope

Variables declared inside a function are local to that function and cannot be accessed from outside. This is called function scope.

JAVASCRIPT
const globalVar = 'I am global';

function myFunction() {
  const localVar = 'I am local';
  console.log(globalVar); // Can access global
  console.log(localVar);  // Can access local
}

myFunction();
// console.log(localVar); // Error: localVar is not defined

// Variables declared with var are function-scoped
function example() {
  if (true) {
    var functionScoped = 'I am function scoped';
    let blockScoped = 'I am block scoped';
  }
  console.log(functionScoped); // Works
  // console.log(blockScoped); // Error: blockScoped is not defined
}

Variables declared with `const` and `let` are block-scoped, while `var` is function-scoped. Function parameters are also local to the function.

Higher-Order Functions

Higher-order functions are functions that take other functions as arguments or return functions. They're powerful for creating reusable, flexible code.

JAVASCRIPT
// Function that takes another function as argument
function operate(a, b, operation) {
  return operation(a, b);
}

const add = (x, y) => x + y;
const multiply = (x, y) => x * y;

console.log(operate(5, 3, add));       // Output: 8
console.log(operate(5, 3, multiply));  // Output: 15

// Function that returns another function
function createMultiplier(factor) {
  return function(number) {
    return number * factor;
  };
}

const double = createMultiplier(2);
const triple = createMultiplier(3);

console.log(double(5));  // Output: 10
console.log(triple(5));  // Output: 15

Higher-order functions enable powerful patterns like function composition and creating specialized functions dynamically.

Complete Example: Calculator Application

Let's build a complete calculator using functions:

JAVASCRIPT
// Calculator functions
const add = (a, b) => a + b;
const subtract = (a, b) => a - b;
const multiply = (a, b) => a * b;
const divide = (a, b) => {
  if (b === 0) {
    return 'Error: Division by zero';
  }
  return a / b;
};

// Main calculator function
function calculate(operation, a, b) {
  const operations = {
    '+': add,
    '-': subtract,
    '*': multiply,
    '/': divide
  };
  
  const operationFunc = operations[operation];
  if (!operationFunc) {
    return 'Error: Invalid operation';
  }
  
  return operationFunc(a, b);
}

// Usage
console.log(calculate('+', 10, 5));  // Output: 15
console.log(calculate('-', 10, 5)); // Output: 5
console.log(calculate('*', 10, 5)); // Output: 50
console.log(calculate('/', 10, 5)); // Output: 2
console.log(calculate('/', 10, 0)); // Output: Error: Division by zero

This calculator demonstrates how to use functions to organize code, handle errors, and create a clean, maintainable structure.

Best practice

Always validate inputs in your functions, especially for mathematical operations. Check for division by zero, invalid operations, and edge cases.

Common Function Patterns

Callback Functions

JAVASCRIPT
// Callback function
function processArray(arr, callback) {
  const result = [];
  for (let item of arr) {
    result.push(callback(item));
  }
  return result;
}

const numbers = [1, 2, 3, 4, 5];
const doubled = processArray(numbers, (num) => num * 2);
console.log(doubled); // Output: [2, 4, 6, 8, 10]

Callbacks are functions passed as arguments to be executed later. They're commonly used in array methods and event handlers.

Immediately Invoked Function Expression (IIFE)

JAVASCRIPT
// IIFE - runs immediately
(function() {
  console.log('This runs immediately!');
})();

// IIFE with parameters
(function(name) {
  console.log(`Hello, ${name}!`);
})('World');

IIFEs are functions that execute immediately after being defined. They're useful for creating isolated scopes.

Practical Examples

Example 1: Basic Function Declaration

function sayHello(name) {
  return `Hello, ${name}!`;
}

console.log(sayHello('Alice'));

Simple function declaration with one parameter and a return value.

Expected Output:

Hello, Alice!

Example 2: Arrow Function with Multiple Parameters

const calculateTotal = (price, tax, discount) => {
  const subtotal = price - discount;
  return subtotal + (subtotal * tax);
};

console.log(calculateTotal(100, 0.1, 10));

Arrow function performing calculations with multiple parameters.

Expected Output:

99

Example 3: Function with Default Parameters

function createGreeting(name = 'Guest', time = 'day') {
  return `Good ${time}, ${name}!`;
}

console.log(createGreeting());
console.log(createGreeting('Alice'));
console.log(createGreeting('Bob', 'evening'));

Functions can have default parameter values that are used when arguments are not provided.

Expected Output:

Good day, Guest! Good day, Alice! Good evening, Bob!

Example 4: Higher-Order Function

function applyOperation(a, b, operation) {
  return operation(a, b);
}

const result1 = applyOperation(10, 5, (x, y) => x + y);
const result2 = applyOperation(10, 5, (x, y) => x * y);

console.log(result1, result2);

Higher-order function that accepts another function as a parameter.

Expected Output:

15 50

Example 5: Function Returning a Function

function createCounter() {
  let count = 0;
  return function() {
    count++;
    return count;
  };
}

const counter = createCounter();
console.log(counter()); // 1
console.log(counter()); // 2
console.log(counter()); // 3

Function that returns another function, creating a closure that maintains state.

Expected Output:

1 2 3

Quiz: Test Your Knowledge

1. What is the main difference between function declarations and function expressions?

2. What does this arrow function return: `const add = (a, b) => a + b`?

3. What happens if you don't use a return statement in a function?

4. What is a closure in JavaScript?

5. What does the rest parameter (`...`) do?

Practice Exercises

Exercise 1: Create a Temperature Converter

Write a function that converts Celsius to Fahrenheit. Formula: F = (C * 9/5) + 32

Show Hints
  • Use function declaration or arrow function
  • Take Celsius as a parameter
  • Return the Fahrenheit value
  • Test with known values (0°C = 32°F, 100°C = 212°F)
Show Solution
const celsiusToFahrenheit = (celsius) => {
  return (celsius * 9/5) + 32;
};

console.log(celsiusToFahrenheit(0));   // 32
console.log(celsiusToFahrenheit(100)); // 212

Exercise 2: Build a String Reverser

Create a function that takes a string and returns it reversed. Use arrow function syntax.

Show Hints
  • Use arrow function
  • Convert string to array, reverse, then join
  • Or use a loop to build reversed string

Exercise 3: Create a Factorial Function

Write a function that calculates the factorial of a number. Factorial of n is n * (n-1) * (n-2) * ... * 1

Show Hints
  • Use recursion or a loop
  • Handle edge case: factorial of 0 is 1
  • Handle negative numbers

Exercise 4: Build a Function Validator

Create a higher-order function that validates input before calling another function. It should return an error message if validation fails.

Show Hints
  • Create a function that takes a validator function and the actual function
  • Return a new function that validates first
  • Call the actual function only if validation passes

Exercise 5: Create a Function Composer

Build a function that composes multiple functions together. For example, compose(f, g, h)(x) should return f(g(h(x))).

Show Hints
  • Use rest parameters to accept multiple functions
  • Use reduceRight to apply functions from right to left
  • Return a new function that applies the composition