JavaScript Tutorial

Functions in JavaScript: Syntax, Types, Examples and Best Practices

Master JavaScript functions including function declarations, expressions, arrow functions, parameters, return values, scope, and best practices with real-world examples.

Welcome back! šŸ‘‹ You've just completed the entire Loops series — amazing work! Now we're stepping into one of the most important concepts in all of JavaScript — Functions!

A function is a reusable block of code designed to perform a specific task. Instead of writing the same logic over and over, you write it once inside a function and call it whenever you need it. Functions are the building blocks of every JavaScript program — from tiny utilities to massive applications.

Let's master them completely!


What is a Function?

A function is a named, reusable block of code that runs only when you call it.

The Problem Functions Solve

Without functions, you repeat yourself constantly:

// āŒ Without functions — repetitive and hard to maintain
console.log("Welcome, Mihir! You have 3 new messages.");
console.log("Welcome, Priya! You have 7 new messages.");
console.log("Welcome, Rahul! You have 1 new messages.");

With a function:

// āœ… With a function — write once, use anywhere
function greetUser(name, messages) {
  console.log(`Welcome, ${name}! You have ${messages} new messages.`);
}

greetUser("Mihir", 3);
greetUser("Priya", 7);
greetUser("Rahul", 1);

Same result. Zero repetition. Easy to update — change the function once and it updates everywhere.


Types of Functions in JavaScript

JavaScript has several ways to define a function. Each has its own syntax and use cases:

  1. Function Declaration — the classic, hoisted way
  2. Function Expression — assign a function to a variable
  3. Arrow Function — modern, concise ES6 syntax
  4. Anonymous Function — function without a name
  5. Default Parameters — parameters with fallback values
  6. Rest Parameters — accept unlimited arguments

1. Function Declaration

The most traditional way to define a function. It is hoisted — meaning you can call it even before it's defined in the code.

Syntax

function functionName(parameters) {
  // code to execute
  return value; // optional
}

Example

function greet(name) {
  console.log(`Hello, ${name}! šŸ‘‹`);
}

greet("Mihir"); // Hello, Mihir! šŸ‘‹
greet("Priya"); // Hello, Priya! šŸ‘‹

Hoisting — Call Before Definition

// āœ… Works! Function declarations are hoisted
sayHello();

function sayHello() {
  console.log("Hello from a hoisted function!");
}
// Output: Hello from a hoisted function!

2. Function Expression

A function stored in a variable. It is not hoisted — you must define it before calling it.

Syntax

const functionName = function(parameters) {
  // code to execute
  return value;
};

Example

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

console.log(multiply(4, 5)); // 20
console.log(multiply(3, 7)); // 21

Not Hoisted

// āŒ Error! Cannot use before defined
console.log(square(5));

const square = function(n) {
  return n * n;
};
// ReferenceError: Cannot access 'square' before initialization

3. Arrow Function

Introduced in ES6, arrow functions are a shorter, cleaner way to write functions. They're now the most commonly used function style in modern JavaScript.

Syntax

// Full arrow function
const functionName = (parameters) => {
  // code
  return value;
};

// Concise — single expression, implicit return
const functionName = (parameters) => expression;

Examples

// Traditional function
function add(a, b) {
  return a + b;
}

// Same as arrow function
const add = (a, b) => a + b;

console.log(add(3, 4)); // 7
// Single parameter — parentheses optional
const double = n => n * 2;
console.log(double(6)); // 12

// No parameters — empty parentheses required
const greet = () => console.log("Hello! šŸ‘‹");
greet();

// Multiple lines — need curly braces and return
const getGrade = (marks) => {
  if (marks >= 90) return "A";
  if (marks >= 75) return "B";
  if (marks >= 60) return "C";
  return "F";
};

console.log(getGrade(85)); // B

Arrow vs Regular — Key Differences

// Regular function — has its own 'this'
function Timer() {
  this.seconds = 0;
  setInterval(function() {
    this.seconds++; // āŒ 'this' refers to the callback scope, not Timer
  }, 1000);
}

// Arrow function — inherits 'this' from parent
function Timer() {
  this.seconds = 0;
  setInterval(() => {
    this.seconds++; // āœ… 'this' correctly refers to Timer
  }, 1000);
}

4. Parameters and Arguments

Parameters are the variables listed in the function definition. Arguments are the actual values passed when calling the function.

//               Parameters ↓   ↓
function introduce(name, role) {
  console.log(`Hi, I'm ${name} and I work as a ${role}.`);
}

//           Arguments ↓         ↓
introduce("Mihir",    "Developer");
introduce("Priya",    "Designer");
// Output:
// Hi, I'm Mihir and I work as a Developer.
// Hi, I'm Priya and I work as a Designer.

Default Parameters

Give parameters a fallback value — used when no argument is passed.

function greet(name = "Guest", greeting = "Hello") {
  console.log(`${greeting}, ${name}! šŸ‘‹`);
}

greet("Mihir", "Welcome");  // Welcome, Mihir! šŸ‘‹
greet("Priya");              // Hello, Priya! šŸ‘‹
greet();                     // Hello, Guest! šŸ‘‹

Rest Parameters

Use ... to accept any number of arguments as an array.

function sumAll(...numbers) {
  let total = 0;
  for (let num of numbers) {
    total += num;
  }
  return total;
}

console.log(sumAll(1, 2, 3));           // 6
console.log(sumAll(10, 20, 30, 40));    // 100
console.log(sumAll(5));                  // 5
function introduce(firstName, lastName, ...hobbies) {
  console.log(`Name: ${firstName} ${lastName}`);
  console.log(`Hobbies: ${hobbies.join(", ")}`);
}

introduce("Mihir", "Shah", "Coding", "Reading", "Gaming");
// Output:
// Name: Mihir Shah
// Hobbies: Coding, Reading, Gaming

5. The return Statement

return sends a value back to wherever the function was called. Once return executes, the function stops immediately.

function square(n) {
  return n * n; // sends back the result
}

let result = square(5);
console.log(result); // 25

Return Stops Execution

function checkAge(age) {
  if (age < 0) {
    return "Invalid age āŒ"; // Exits immediately
  }
  if (age < 18) {
    return "Minor šŸ‘¶";
  }
  return "Adult šŸ§‘"; // Only reached if age >= 18
}

console.log(checkAge(-1));  // Invalid age āŒ
console.log(checkAge(15));  // Minor šŸ‘¶
console.log(checkAge(22));  // Adult šŸ§‘

Functions Without return

A function with no return statement returns undefined.

function sayHi() {
  console.log("Hi!");
  // no return
}

let val = sayHi(); // prints "Hi!"
console.log(val);  // undefined

Returning Multiple Values via Object

function getMinMax(numbers) {
  let min = Math.min(...numbers);
  let max = Math.max(...numbers);
  return { min, max }; // return as an object
}

let { min, max } = getMinMax([3, 1, 9, 5, 7]);
console.log(`Min: ${min}, Max: ${max}`);
// Output: Min: 1, Max: 9

6. Function Scope

Variables declared inside a function are local — they only exist within that function and cannot be accessed from outside.

function calculate() {
  let result = 42; // local variable
  console.log(result); // āœ… accessible here
}

calculate();
console.log(result); // āŒ ReferenceError: result is not defined

Local vs Global Scope

let message = "I am global šŸŒ"; // global variable

function showMessage() {
  let message = "I am local šŸ“¦"; // local variable — shadows global
  console.log(message);
}

showMessage();          // I am local šŸ“¦
console.log(message);  // I am global šŸŒ

Functions Can Read Global Variables

let taxRate = 0.18;

function calculatePrice(basePrice) {
  return basePrice + basePrice * taxRate; // reads global taxRate āœ…
}

console.log(calculatePrice(1000)); // 1180

7. Higher-Order Functions

A higher-order function is a function that either takes another function as an argument, or returns a function. This is one of the most powerful patterns in JavaScript.

Function as Argument

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

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

console.log(applyOperation(10, 3, add));       // 13
console.log(applyOperation(10, 3, subtract));  // 7
console.log(applyOperation(10, 3, multiply));  // 30

Function Returning a Function

function createMultiplier(factor) {
  return (number) => number * factor;
}

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

console.log(double(5));   // 10
console.log(triple(5));   // 15
console.log(times10(5));  // 50

Real-World Examples

Example 1: Temperature Converter

const celsiusToFahrenheit = (c) => (c * 9/5) + 32;
const fahrenheitToCelsius = (f) => (f - 32) * 5/9;

console.log(`25°C = ${celsiusToFahrenheit(25)}°F`);   // 25°C = 77°F
console.log(`98.6°F = ${fahrenheitToCelsius(98.6).toFixed(1)}°C`); // 37.0°C

Example 2: Validate Email

function isValidEmail(email) {
  return email.includes("@") && email.includes(".");
}

console.log(isValidEmail("mihir@example.com")); // true
console.log(isValidEmail("mihirexample.com"));  // false
console.log(isValidEmail("mihir@example"));     // false

Example 3: Calculate Discount

function calculateDiscount(price, discountPercent) {
  if (discountPercent < 0 || discountPercent > 100) {
    return "Invalid discount percentage āŒ";
  }
  let discountAmount = (price * discountPercent) / 100;
  let finalPrice = price - discountAmount;
  return {
    original:   price,
    discount:   discountAmount,
    finalPrice: finalPrice,
  };
}

let result = calculateDiscount(5000, 20);
console.log(`Original:  ₹${result.original}`);
console.log(`Discount:  ₹${result.discount}`);
console.log(`You Pay:   ₹${result.finalPrice}`);
// Output:
// Original:  ₹5000
// Discount:  ₹1000
// You Pay:   ₹4000

Example 4: Generate a Student Report

function generateReport(students) {
  let report = [];

  for (let student of students) {
    let grade  = student.marks >= 90 ? "A"
               : student.marks >= 75 ? "B"
               : student.marks >= 60 ? "C"
               : "F";
    let status = student.marks >= 40 ? "Pass āœ…" : "Fail āŒ";

    report.push({ ...student, grade, status });
  }

  return report;
}

let students = [
  { name: "Mihir", marks: 92 },
  { name: "Priya", marks: 78 },
  { name: "Rahul", marks: 35 },
  { name: "Sara",  marks: 65 },
];

let report = generateReport(students);

console.log("=== šŸ“Š Report Card ===");
for (let s of report) {
  console.log(`${s.name.padEnd(8)} | ${s.marks} marks | Grade: ${s.grade} | ${s.status}`);
}
// Output:
// Mihir    | 92 marks | Grade: A | Pass āœ…
// Priya    | 78 marks | Grade: B | Pass āœ…
// Rahul    | 35 marks | Grade: F | Fail āŒ
// Sara     | 65 marks | Grade: C | Pass āœ…

Example 5: Shopping Cart Functions

function addItem(cart, item) {
  return [...cart, item];
}

function removeItem(cart, itemName) {
  return cart.filter(item => item.name !== itemName);
}

function getTotal(cart) {
  return cart.reduce((total, item) => total + item.price * item.qty, 0);
}

let cart = [];
cart = addItem(cart, { name: "Laptop",  price: 55000, qty: 1 });
cart = addItem(cart, { name: "Mouse",   price: 800,   qty: 2 });
cart = addItem(cart, { name: "Bag",     price: 1200,  qty: 1 });

console.log("Cart:", cart.map(i => i.name).join(", "));
console.log("Total: ₹" + getTotal(cart));

cart = removeItem(cart, "Bag");
console.log("After removal:", cart.map(i => i.name).join(", "));
console.log("New Total: ₹" + getTotal(cart));
// Output:
// Cart: Laptop, Mouse, Bag
// Total: ₹57800
// After removal: Laptop, Mouse
// New Total: ₹56600

Common Mistakes

Mistake 1: Calling Without Parentheses

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

// āŒ Just references the function — doesn't call it
console.log(greet);   // [Function: greet]

// āœ… Parentheses are required to execute
greet();              // Hello! āœ…

Mistake 2: Forgetting return

function add(a, b) {
  a + b; // āŒ Calculates but doesn't return — lost!
}

console.log(add(2, 3)); // undefined āŒ

// āœ… Always return the result
function add(a, b) {
  return a + b;
}
console.log(add(2, 3)); // 5 āœ…

Mistake 3: Shadowing with Same Variable Name

let total = 100;

function addTax(price) {
  let total = price * 1.18; // āŒ Creates a new local 'total', shadows global
  return total;
}

console.log(addTax(500)); // 590
console.log(total);       // Still 100 — global unchanged (but confusing!)

// āœ… Use distinct names to avoid confusion
function addTax(price) {
  let priceWithTax = price * 1.18;
  return priceWithTax;
}

Mistake 4: Too Many Parameters

// āŒ Hard to read and easy to pass arguments in wrong order
function createUser(name, age, email, city, role, isActive) {
  // ...
}
createUser("Mihir", 25, "mihir@ex.com", "Mumbai", "admin", true);

// āœ… Use an object parameter instead
function createUser({ name, age, email, city, role, isActive }) {
  console.log(`${name} | ${role} | ${city}`);
}
createUser({
  name: "Mihir",
  age: 25,
  email: "mihir@ex.com",
  city: "Mumbai",
  role: "admin",
  isActive: true,
});

Practical Exercise

Create a file called functions.js:

// šŸŽÆ Functions Practice

// 1. Basic utility functions
const isEven     = (n) => n % 2 === 0;
const isPositive = (n) => n > 0;
const clamp      = (n, min, max) => Math.min(Math.max(n, min), max);
const percentage = (value, total) => ((value / total) * 100).toFixed(2) + "%";

console.log("=== Utilities ===");
console.log(isEven(4));            // true
console.log(isPositive(-3));       // false
console.log(clamp(15, 0, 10));     // 10
console.log(percentage(45, 200));  // 22.50%


// 2. Grade calculator with report
function getGrade(marks) {
  if (marks >= 90) return { grade: "A+", label: "Outstanding 🌟" };
  if (marks >= 80) return { grade: "A",  label: "Excellent šŸŽ‰"  };
  if (marks >= 70) return { grade: "B",  label: "Good šŸ‘"       };
  if (marks >= 60) return { grade: "C",  label: "Average šŸ™‚"    };
  if (marks >= 40) return { grade: "D",  label: "Below Avg āš ļø"  };
  return             { grade: "F",  label: "Failed āŒ"       };
}

console.log("\n=== Grade Report ===");
let testMarks = [95, 83, 71, 62, 45, 30];
for (let marks of testMarks) {
  let { grade, label } = getGrade(marks);
  console.log(`Marks: ${marks} → Grade: ${grade} (${label})`);
}


// 3. Shopping cart
function createCart() {
  let cart = [];

  return {
    add(item) {
      cart.push(item);
      console.log(`āœ… Added: ${item.name}`);
    },
    remove(name) {
      cart = cart.filter(i => i.name !== name);
      console.log(`šŸ—‘ļø  Removed: ${name}`);
    },
    total() {
      return cart.reduce((sum, i) => sum + i.price * i.qty, 0);
    },
    summary() {
      console.log("\nšŸ›’ Cart Summary:");
      for (let item of cart) {
        console.log(`  ${item.name.padEnd(10)}: ₹${item.price} Ɨ ${item.qty} = ₹${item.price * item.qty}`);
      }
      console.log(`  ${"─".repeat(35)}`);
      console.log(`  TOTAL: ₹${this.total()}`);
    },
  };
}

console.log("\n=== Shopping Cart ===");
let myCart = createCart();
myCart.add({ name: "Laptop",  price: 55000, qty: 1 });
myCart.add({ name: "Mouse",   price: 800,   qty: 2 });
myCart.add({ name: "Bag",     price: 1200,  qty: 1 });
myCart.remove("Bag");
myCart.summary();

Run it:

node functions.js

Expected Output:

=== Utilities ===
true
false
10
22.50%

=== Grade Report ===
Marks: 95 → Grade: A+ (Outstanding 🌟)
Marks: 83 → Grade: A  (Excellent šŸŽ‰)
Marks: 71 → Grade: B  (Good šŸ‘)
...

=== Shopping Cart ===
āœ… Added: Laptop
āœ… Added: Mouse
āœ… Added: Bag
šŸ—‘ļø  Removed: Bag

šŸ›’ Cart Summary:
  Laptop    : ₹55000 Ɨ 1 = ₹55000
  Mouse     : ₹800 Ɨ 2   = ₹1600
  ───────────────────────────────────
  TOTAL: ₹56600

Key Takeaways

Congratulations! šŸŽ‰ You now have a solid foundation of JavaScript functions.

āœ… Functions are reusable blocks of code — write once, use anywhere.

āœ… 3 main types:

  • function declaration — hoisted, traditional
  • function expression — not hoisted, stored in variable
  • arrow function — concise, modern, no own this

āœ… Parameters vs Arguments:

  • Parameters = placeholders in the definition
  • Arguments = actual values passed when calling

āœ… Default parameters provide fallback values when arguments are missing.

āœ… Rest parameters (...args) accept unlimited arguments as an array.

āœ… return sends a value back and stops function execution immediately.

āœ… Scope — variables inside a function are local; they don't leak outside.

āœ… Higher-order functions — functions that accept or return other functions — are the backbone of modern JavaScript.


Best Practices

  1. āœ… Give functions a clear, descriptive name that says what they do — calculateTax, not ct
  2. āœ… Each function should do one thing only — keep it focused
  3. āœ… Keep functions short — if it's over 20 lines, consider splitting it
  4. āœ… Use default parameters instead of checking for undefined manually
  5. āœ… Use object parameters when a function needs more than 3 arguments
  6. āœ… Always return a value from functions meant to compute something
  7. āœ… Prefer arrow functions for short callbacks and expressions
  8. āœ… Use function declarations for main, named functions — they hoist and are easy to find

What's Next?

Excellent work! šŸŽ‰ Functions are the backbone of everything you'll write in JavaScript from here on.

Next, we're diving into Arrow Functions → — the modern, concise way to write functions that you'll be using constantly. You'll learn their syntax, how they differ from regular functions, and when to use them for maximum readability and performance.

You'll learn how to manipulate, search, transform, and format text like a pro. Let's go! šŸ’Ŗ