Almost everything in JavaScript involves functions. You use them to organise your code into reusable pieces, to respond to user events, to transform data and to build entire applications. Understanding functions deeply is not optional — it is the most important skill in JavaScript.

The good news is that JavaScript gives you many different ways to write functions, and each one has a purpose. By the end of this guide you will know exactly which kind to use in any situation, how they each behave, and some powerful patterns like closures and higher-order functions that experienced developers use every day.

Download This Article as a Cheat Sheet Save a clean PDF summary of all JavaScript function types, syntax and examples for offline reference.
PDF  ·  1 page  ·  Free

What Is a Function

A function is a reusable block of code that performs a specific job. You write it once and can run it as many times as you want, from anywhere in your code. You can even give it different inputs each time to get different results.

Think of a function like a recipe. You write the recipe once. Every time you want to cook that dish you follow the same recipe, but you might use different quantities each time — more spice today, less tomorrow. The recipe itself does not change.

In JavaScript, functions are "first-class citizens" — which means you can store them in variables, pass them to other functions as arguments, and return them from other functions. This is what makes JavaScript so flexible and powerful.


Function Declarations

The most traditional way to create a function is with the function keyword followed by a name. This is called a function declaration.

JavaScript — basic function declaration
// Define the function function greet(name) { return `Hello, ${name}!`; } // Call the function console.log(greet('Shashank')); // Hello, Shashank! console.log(greet('Priya')); // Hello, Priya! // A function with multiple parameters function add(a, b) { return a + b; } console.log(add(3, 7)); // 10

Hoisting — Call Before You Define

Function declarations are hoisted. This means JavaScript moves them to the top of the current scope before any code runs. So you can actually call a function declaration before the line where you wrote it. This is unique to function declarations.

JavaScript — function declarations are hoisted
// This works even though greet is defined BELOW this line console.log(greet('Shashank')); // Hello, Shashank! function greet(name) { return `Hello, ${name}!`; }

Function Expressions — Functions as Values

You can also create a function and assign it to a variable. This is called a function expression. The function itself has no name (it is anonymous). The variable name is how you call it.

Function expressions are not hoisted. If you try to call one before the line where it is assigned, you will get an error.

JavaScript — function expressions stored in variables
// Anonymous function expression const greet = function(name) { return `Hello, ${name}!`; }; console.log(greet('Shashank')); // Hello, Shashank! // Named function expression — the name only exists inside the function itself // Useful for recursion and better stack traces const factorial = function calc(n) { if (n <= 1) return 1; return n * calc(n - 1); // uses the internal name 'calc' to recurse }; console.log(factorial(5)); // 120

Arrow Functions — The Modern Shorthand

Arrow functions are a shorter way to write function expressions, introduced in ES6. They use the => syntax and are now the most common way to write small functions in modern JavaScript code.

JavaScript — arrow function syntax in all its forms
// Full arrow function const greet = (name) => { return `Hello, ${name}!`; }; // Single parameter — parentheses are optional const greet = name => { return `Hello, ${name}!`; }; // Single expression — curly braces and return are optional // The expression is automatically returned const greet = name => `Hello, ${name}!`; // No parameters — empty parentheses are required const sayHi = () => 'Hi!'; // Multiple parameters — parentheses always required const add = (a, b) => a + b; // Returning an object — wrap it in parentheses to avoid confusion with a block const makeUser = name => ({ name, active: true }); console.log(greet('Shashank')); // Hello, Shashank! console.log(add(4, 6)); // 10 console.log(makeUser('Rahul')); // { name: 'Rahul', active: true }

Arrow Functions and this

The most important difference between arrow functions and regular functions is how they handle this. Regular functions create their own this context. Arrow functions do not — they inherit this from the surrounding code. This makes arrow functions very useful inside class methods and event handlers.

JavaScript — this behaves differently in arrow vs regular functions
class Timer { constructor() { this.seconds = 0; } startBroken() { // Regular function creates its own 'this' — loses the class reference setInterval(function() { this.seconds++; // 'this' is undefined here — TypeError! }, 1000); } startFixed() { // Arrow function inherits 'this' from startFixed — works correctly setInterval(() => { this.seconds++; // 'this' is the Timer instance console.log(this.seconds); }, 1000); } }
ℹ️ When to use each: use arrow functions for short callbacks, array methods and anywhere you want to inherit this. Use regular function declarations for top-level named functions that might benefit from hoisting. Both are correct — context matters.

Parameters in Depth

Default Parameters

You can give a parameter a default value. If the caller does not pass that argument (or passes undefined), the default is used automatically.

JavaScript — default parameter values
function greet(name = 'friend', greeting = 'Hello') { return `${greeting}, ${name}!`; } console.log(greet()); // Hello, friend! console.log(greet('Shashank')); // Hello, Shashank! console.log(greet('Priya', 'Namaste')); // Namaste, Priya! // Default values can even be expressions or other function calls const createId = () => Math.random().toString(36).slice(2); function createUser(name, id = createId()) { return { name, id }; }

Rest Parameters — Collect Extra Arguments

The rest parameter ...args collects all remaining arguments into an array. It must always be the last parameter. This is how you write functions that accept any number of arguments.

JavaScript — rest parameters collect unlimited arguments
function sum(...numbers) { return numbers.reduce((total, n) => total + n, 0); } console.log(sum(1, 2, 3)); // 6 console.log(sum(10, 20, 30, 40, 50)); // 150 // Mix fixed and rest parameters function logMessage(level, ...parts) { console.log(`[${level}]`, parts.join(' ')); } logMessage('ERROR', 'Something', 'went', 'wrong'); // [ERROR] Something went wrong

Destructuring Parameters

Instead of passing a big object and accessing properties inside the function, you can destructure right in the parameter list. This makes function signatures self-documenting.

JavaScript — object destructuring in function parameters
// Without destructuring — verbose, repetitive function displayUser(user) { console.log(user.name, user.age, user.city); } // With destructuring — clean and self-documenting function displayUser({ name, age, city }) { console.log(name, age, city); } // Combine destructuring with default values function createButton({ text = 'Click me', color = 'blue', disabled = false } = {}) { return `<button style="color:${color}" ${disabled ? 'disabled' : ''}>${text}</button>`; } console.log(createButton()); // all defaults console.log(createButton({ text: 'Submit', color: 'green' }));

Return Values

A function sends a value back to the caller using return. As soon as JavaScript hits a return statement, it stops executing the function and sends that value back. Functions that do not have a return statement automatically return undefined.

JavaScript — return values and early returns
// Return stops execution immediately function divide(a, b) { if (b === 0) { return null; // early return — exits here if b is zero } return a / b; // only reaches here if b is not zero } console.log(divide(10, 2)); // 5 console.log(divide(10, 0)); // null — safely handled // Functions can return any value — including objects, arrays or other functions function getUser(id) { return { id, name: 'Shashank', role: 'developer' }; }

Scope — Where Variables Live

Scope is about visibility — which parts of your code can "see" and use a variable. Variables declared inside a function are local to that function. They are created when the function runs and destroyed when it finishes. Outside code cannot see them.

JavaScript — local scope inside functions
const globalMessage = 'I am global'; function showMessage() { const localMessage = 'I am local'; console.log(globalMessage); // works — functions can see global variables console.log(localMessage); // works — inside the function } showMessage(); console.log(globalMessage); // works console.log(localMessage); // ReferenceError — localMessage does not exist out here

Closures — Functions That Remember

A closure is a function that remembers the variables from the scope it was created in, even after that outer function has finished running. This sounds confusing but it is one of the most useful and powerful features in JavaScript.

Think of it like a backpack. When a function is created, it gets a backpack containing all the variables from its surrounding scope. Even if the outer function finishes, the inner function still has its backpack and can use those variables.

JavaScript — closures explained with a counter example
function makeCounter() { let count = 0; // this variable lives in the closure return function() { count++; return count; }; } const counter1 = makeCounter(); const counter2 = makeCounter(); // separate closure, separate count console.log(counter1()); // 1 console.log(counter1()); // 2 console.log(counter1()); // 3 console.log(counter2()); // 1 — counter2 has its own independent count // Practical use: create a function with locked-in configuration function createMultiplier(multiplier) { return n => n * multiplier; // closes over 'multiplier' } const double = createMultiplier(2); const triple = createMultiplier(3); console.log(double(5)); // 10 console.log(triple(5)); // 15

Higher-Order Functions

A higher-order function is any function that either takes another function as an argument, returns a function, or both. Because JavaScript functions are first-class values, you can pass them around just like numbers or strings.

Higher-order functions are extremely common in JavaScript. Every time you use .map(), .filter(), .forEach() or .reduce() on an array, you are using a higher-order function.

map, filter and reduce

JavaScript — map, filter and reduce explained
const numbers = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]; // map — transforms every element, returns a NEW array of the same length const doubled = numbers.map(n => n * 2); console.log(doubled); // [2, 4, 6, 8, 10, 12, 14, 16, 18, 20] // filter — keeps only elements where the function returns true const evens = numbers.filter(n => n % 2 === 0); console.log(evens); // [2, 4, 6, 8, 10] // reduce — collapses the array into a single value const total = numbers.reduce((sum, n) => sum + n, 0); console.log(total); // 55 // Chain them together — filter first, then double, then total const sumOfDoubledEvens = numbers .filter(n => n % 2 === 0) // [2, 4, 6, 8, 10] .map(n => n * 2) // [4, 8, 12, 16, 20] .reduce((sum, n) => sum + n, 0); // 60 console.log(sumOfDoubledEvens); // 60

Callbacks — Passing Functions as Arguments

A callback is a function you pass to another function so it can be called later. Callbacks are everywhere in JavaScript — event listeners, timers, array methods and async operations all use them.

JavaScript — callbacks in different situations
// A function that accepts a callback function processData(data, callback) { const result = data.filter(x => x > 0); callback(result); // call the callback when done } // Pass a named function as the callback function printResults(items) { console.log('Positive numbers:', items); } processData([-3, 1, -1, 4, 7], printResults); // Or pass an inline arrow function directly processData([-3, 1, -1, 4, 7], items => console.log(items)); // Event listener callback document.getElementById('btn').addEventListener('click', function() { console.log('Button was clicked!'); }); // setTimeout callback — runs after 2 seconds setTimeout(() => console.log('2 seconds later!'), 2000);

IIFE — Immediately Invoked Function Expression

An IIFE (pronounced "iffy") is a function that runs immediately as soon as it is defined. You wrap the function in parentheses and then add () at the end to call it right away. It is used to create a private scope and avoid polluting the global namespace.

JavaScript — IIFE creates a private scope
// The function is wrapped in () and called immediately with () (function() { const secret = 'only visible inside here'; console.log(secret); })(); // Arrow function IIFE (() => { console.log('IIFE with arrow function'); })(); // IIFE with a parameter (function(name) { console.log(`Hello, ${name}!`); })('Shashank'); // Hello, Shashank!

Pure Functions — Predictable and Testable

A pure function always returns the same output for the same input and has no side effects (does not modify external data, does not talk to a database, does not change a global variable). Pure functions are easy to test, easy to reason about and behave predictably every time.

JavaScript — pure vs impure functions
// IMPURE — depends on and modifies external state let total = 0; function addToTotal(amount) { total += amount; // modifies external variable — side effect return total; // result depends on external state } // PURE — only uses its inputs, does not touch anything outside function add(a, b) { return a + b; // always returns a + b. No surprises. No side effects. } // PURE — works with data without modifying the original function addItem(cart, item) { return [...cart, item]; // returns a NEW array, does not mutate 'cart' } const myCart = ['apple', 'banana']; const newCart = addItem(myCart, 'cherry'); console.log(myCart); // ['apple', 'banana'] — unchanged console.log(newCart); // ['apple', 'banana', 'cherry']

Quick Reference

Function TypeSyntaxHoistedOwn thisBest For
Declarationfunction name() {}YesYesTop-level named functions
Expressionconst f = function() {}NoYesConditionally defined functions
Arrowconst f = () => {}NoNo (inherits)Callbacks, short functions, classes
IIFE(function() {})()NoYesPrivate scope, one-time setup

⚡ Key Takeaways
  • Function declarations use the function name() {} syntax and are hoisted — you can call them before the line where they are written.
  • Function expressions store a function in a variable. They are not hoisted. The function itself is usually anonymous.
  • Arrow functions (() => {}) are shorter and do not have their own this. Single-expression arrows return automatically without needing the return keyword.
  • Default parameters let you set fallback values that are used when an argument is not passed. Rest parameters (...args) collect unlimited extra arguments into an array.
  • Destructuring parameters pull named properties directly from an object argument, making function signatures cleaner and self-documenting.
  • return stops the function immediately and sends a value back. Functions without return give back undefined. Use early returns to handle edge cases at the top of a function.
  • Variables declared inside a function are local — they cannot be seen from outside. Functions can read outer (global) variables, but outside code cannot see local variables.
  • A closure is a function that remembers variables from the scope it was created in. Each closure gets its own copy of those variables. This enables patterns like counter factories and function configuration.
  • Higher-order functions take functions as arguments or return functions. map transforms, filter keeps matching elements, reduce collapses to one value.
  • A pure function always returns the same output for the same input and has no side effects. Prefer pure functions wherever possible — they are predictable, testable and safe to use anywhere.
📄
Save This Guide as a PDF A one-page cheat sheet covering all JavaScript function types, syntax patterns and key differences. Great for quick reference.
PDF  ·  1 page  ·  Free