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 linesconst 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 oncefunctiongreet(name) {
console.log(`Hello, ${name}!`);
}
// Call many times with different inputsgreet("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!functionsayHello() {
console.log("Hello World!");
}
// Function with parametersfunctionadd(a, b) {
return a + b;
}
console.log(add(5, 3)); // 8
console.log(add(10, 20)); // 30// Real world — validate emailfunctionisValidEmail(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 variableconst greet = function(name) {
return`Hello, ${name}!`;
};
console.log(greet("Waheed")); // Hello, Waheed!// Function passed as argumentconst 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 definitionconst 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 functionconst add = function(a, b) { return a + b; }
const add = (a, b) => { return a + b; } // arrowconst add = (a, b) => a + b; // implicit return// Single parameter — no parentheses neededconst double = n => n * 2;
console.log(double(5)); // 10// No parameters — empty parentheses requiredconst sayHi = () => "Hello!";
console.log(sayHi()); // Hello!// Arrow functions in array methodsconst 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:
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 — undefinedfunctionnoReturn() {
2 + 2;
}
console.log(noReturn()); // undefined// With return — get value backfunctionwithReturn() {
return2 + 2;
}
console.log(withReturn()); // 4// return exits function immediatelyfunctioncheckAge(age) {
if (age < 0) return"Invalid age"; // early returnif (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 valuesconst 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 whereconst globalVar = "I am global";
functionouter() {
const outerVar = "I am outer";
functioninner() {
const innerVar = "I am inner";
console.log(globalVar); // ✅ can access
console.log(outerVar); // ✅ can access
console.log(innerVar); // ✅ can access
}
// console.log(innerVar); // ❌ cannot accessinner();
}
outer();
// Closure — function remembers outer variablesfunctionmakeCounter() {
let count = 0; // remembered by closurereturnfunction() {
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.