JavaScript Roadmap — Day 13: Functions

 

JavaScript · Day 13 of 180 · Beginner Phase

Functions

Functions are the most important concept in JavaScript. They are reusable blocks of code that make your programs organized, readable, and powerful. Everything in modern JavaScript is built around functions.

Day 13 / 180
Beginner Phase
🕐 14 min read
💻 7 code examples
🎯 3 practice tasks

Imagine you are building an app. Every time a user logs in you need to: validate the email, check the password, update the last login time, and show a welcome message. Without functions your code looks like this:

Without functions — repeated code everywhere
// Login page — 20 lines
const email1 = "waheed@gmail.com";
if (!email1.includes("@")) console.log("Invalid");
// check password... update time... show message...

// Registration page — same 20 lines again 😩
const email2 = "ali@gmail.com";
if (!email2.includes("@")) console.log("Invalid");
// same code repeated...

With functions you write that logic once — then call it anywhere, anytime, with any data. This is the DRY principle — Don't Repeat Yourself. It is the most important rule in software development. Functions are how you follow it.

1. What is a Function?

A function is a named, reusable block of code. You define it once and call it as many times as you need — with different inputs each time. Think of it like a recipe — you write it once and cook it whenever you want:

JavaScript — Function Basics
// Define once
function greet(name) {
  console.log(`Hello, ${name}!`);
}

// Call many times with different inputs
greet("Waheed");  // Hello, Waheed!
greet("Ali");     // Hello, Ali!
greet("Sara");    // Hello, Sara!

// Without function — same code 3 times
console.log("Hello, Waheed!");
console.log("Hello, Ali!");
console.log("Hello, Sara!");

2. Function Declaration — The Classic Way

A function declaration uses the function keyword followed by a name. The key feature is hoisting — you can call it before it is defined in your code:

JavaScript — Function Declaration
// Call BEFORE definition — works due to hoisting!
sayHello();  // Hello World! ← works!

function sayHello() {
  console.log("Hello World!");
}

// Function with parameters
function add(a, b) {
  return a + b;
}
console.log(add(5, 3));  // 8
console.log(add(10, 20)); // 30

// Real world — validate email
function isValidEmail(email) {
  return email.includes("@") && email.includes(".");
}
console.log(isValidEmail("waheed@gmail.com")); // true
console.log(isValidEmail("waheedgmail"));      // false

3. Function Expression — Functions as Values

In JavaScript functions are first-class citizens — they can be stored in variables, passed as arguments, and returned from other functions. A function expression stores a function in a variable:

JavaScript — Function Expression
// Function stored in a variable
const greet = function(name) {
  return `Hello, ${name}!`;
};
console.log(greet("Waheed")); // Hello, Waheed!

// Function passed as argument
const numbers = [1, 2, 3, 4, 5];
const doubled = numbers.map(function(n) {
  return n * 2;
});
console.log(doubled); // [2, 4, 6, 8, 10]

// Key difference — NOT hoisted
// greet2(); // ❌ Error — cannot call before definition
const greet2 = function(name) {
  return `Hi ${name}`;
};

4. Arrow Functions — Modern JavaScript 🔥

Arrow functions are the ES6 shorthand for function expressions. They are shorter, cleaner, and are used everywhere in modern JavaScript and React. You will write these every single day:

JavaScript — Arrow Functions
// Regular function → Arrow function
const add = function(a, b) { return a + b; }
const add = (a, b) => { return a + b; }  // arrow
const add = (a, b) => a + b;              // implicit return

// Single parameter — no parentheses needed
const double = n => n * 2;
console.log(double(5)); // 10

// No parameters — empty parentheses required
const sayHi = () => "Hello!";
console.log(sayHi()); // Hello!

// Arrow functions in array methods
const nums    = [1, 2, 3, 4, 5];
const evens   = nums.filter(n => n % 2 === 0);
const doubled = nums.map(n => n * 2);
const sum     = nums.reduce((acc, n) => acc + n, 0);

console.log(evens);   // [2, 4]
console.log(doubled); // [2, 4, 6, 8, 10]
console.log(sum);     // 15

5. Parameters & Arguments — Passing Data

Parameters are the variables listed in the function definition. Arguments are the actual values passed when calling. JavaScript has powerful features for handling them:

JavaScript — Parameters & Arguments
// Default parameters — ES6
function greet(name = "Guest", greeting = "Hello") {
  return `${greeting}, ${name}!`;
}
console.log(greet());                    // Hello, Guest!
console.log(greet("Waheed"));             // Hello, Waheed!
console.log(greet("Waheed", "Welcome")); // Welcome, Waheed!

// Rest parameters — collect remaining args
function sum(...numbers) {
  return numbers.reduce((total, n) => total + n, 0);
}
console.log(sum(1, 2, 3));          // 6
console.log(sum(1, 2, 3, 4, 5));    // 15
console.log(sum(10, 20, 30, 40));   // 100

// Destructuring parameters
function displayUser({ name, city, salary }) {
  console.log(`${name} from ${city} earns Rs${salary}`);
}
displayUser({ name: "Waheed", city: "Faisalabad", salary: 150000 });
// Waheed from Faisalabad earns Rs150000

6. Return Values — Getting Data Back

The return statement sends a value back from a function. Without it the function returns undefined. Understanding return values is essential for writing useful, composable functions:

JavaScript — Return Values
// Without return — undefined
function noReturn() {
  2 + 2;
}
console.log(noReturn()); // undefined

// With return — get value back
function withReturn() {
  return 2 + 2;
}
console.log(withReturn()); // 4

// return exits function immediately
function checkAge(age) {
  if (age < 0) return "Invalid age"; // early return
  if (age < 18) return "Minor";
  return "Adult";
}
console.log(checkAge(-5)); // Invalid age
console.log(checkAge(15)); // Minor
console.log(checkAge(25)); // Adult

// Chaining functions with return values
const double = n => n * 2;
const square = n => n * n;
const addTen = n => n + 10;

console.log(addTen(square(double(3)))); // addTen(square(6)) → addTen(36) → 46
Pro Tip #1 — Use early returns to avoid nesting
Instead of deeply nested if/else — use early returns to handle edge cases first. This keeps your main logic at the top level and makes code much easier to read. Professional developers call this the "guard clause" pattern.
Pro Tip #2 — Functions should do ONE thing
A function named validateAndSaveUser does two things — that is a red flag. Split it into validateUser() and saveUser(). Single responsibility makes functions reusable, testable, and easy to debug.
Pro Tip #3 — Pure functions are the gold standard
A pure function always returns the same output for the same input and has no side effects. add(2, 3) always returns 5 — no matter what. Pure functions are predictable, testable, and the foundation of functional programming in JavaScript.

7. Scope & Closures — Advanced but Essential 🔥

Scope determines which variables a function can access. Closures are one of JavaScript's most powerful features — a function that remembers the variables from its outer scope even after that scope has finished executing:

JavaScript — Scope & Closures
// Scope — what can be accessed where
const globalVar = "I am global";

function outer() {
  const outerVar = "I am outer";

  function inner() {
    const innerVar = "I am inner";
    console.log(globalVar); // ✅ can access
    console.log(outerVar);  // ✅ can access
    console.log(innerVar);  // ✅ can access
  }
  // console.log(innerVar); // ❌ cannot access
  inner();
}
outer();

// Closure — function remembers outer variables
function makeCounter() {
  let count = 0; // remembered by closure

  return function() {
    count++;
    return count;
  };
}

const counter = makeCounter();
console.log(counter()); // 1
console.log(counter()); // 2
console.log(counter()); // 3
// count is private — cannot access from outside!

8. Try It Yourself

Edit the code and click Run Code. Try creating your own functions and experiment with arrow functions!

✏️ Try it Yourself — Functions
OUTPUT
// Click Run Code to see output
💡 Edit the code and click Run!

9. Practice Tasks

Task 1 — Easy: Calculator Functions

Write four arrow functions — add, subtract, multiply, divide. Each takes two parameters. Add validation to divide — if the second number is 0 return "Cannot divide by zero". Test all four with different values.

Task 2 — Medium: User Profile Builder

Write a function createProfile(name, age, city, skills) using destructuring parameters. Use default values — city defaults to "Pakistan", skills defaults to empty array. Return a formatted profile object. Then write another function displayProfile(profile) that prints it nicely.

Task 3 — Hard: makeMultiplier Closure

Write a function makeMultiplier(factor) that returns a new function. The returned function multiplies any number by the factor. Use it to create double, triple, and times10 functions. This is the closure pattern used in real React hooks and utility libraries.

Next Lesson
Day 14 — Arrays — Complete Guide
View Full Roadmap →
Enjoying this roadmap?
Follow Muhammad Waheed Asghar for daily JavaScript tips and updates!

Popular Posts