Functions

Declarations, expressions, arrow functions

Functions in JavaScript

Functions are reusable blocks of code that perform specific tasks. They're fundamental to organizing and structuring your code.

Function Declaration

The traditional way to define a function:

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

console.log(greet("Alice"));  // "Hello, Alice!"

// Functions can have multiple parameters
function add(a, b) {
  return a + b;
}

console.log(add(5, 3));  // 8

// Functions can have default parameters
function welcome(name = "Guest") {
  return `Welcome, ${name}!`;
}

console.log(welcome());         // "Welcome, Guest!"
console.log(welcome("Bob"));   // "Welcome, Bob!"

Function Expression

Assign a function to a variable:

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

console.log(greet("Charlie"));  // "Hello, Charlie!"

// Anonymous function (no name after 'function')
const numbers = [1, 2, 3, 4, 5];
const doubled = numbers.map(function(num) {
  return num * 2;
});

Arrow Functions

Modern, concise syntax (ES6+):

// Basic arrow function
const greet = (name) => {
  return `Hello, ${name}!`;
};

// Implicit return (no curly braces)
const add = (a, b) => a + b;

// Single parameter (no parentheses needed)
const square = x => x * x;

// No parameters (parentheses required)
const sayHi = () => "Hi!";

// Perfect for array methods
const numbers = [1, 2, 3, 4, 5];
const doubled = numbers.map(num => num * 2);
const evens = numbers.filter(num => num % 2 === 0);

Return Values

Functions can return values or perform actions:

// Returning a value
function multiply(a, b) {
  return a * b;
}

const result = multiply(4, 5);  // 20

// No return statement = returns undefined
function logMessage(msg) {
  console.log(msg);
  // No return
}

const value = logMessage("Hi");  // undefined

// Early return
function divide(a, b) {
  if (b === 0) {
    return "Cannot divide by zero";
  }
  return a / b;
}

Rest Parameters

Accept unlimited arguments:

function sum(...numbers) {
  return numbers.reduce((total, num) => total + num, 0);
}

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

// Mix regular and rest parameters
function introduce(greeting, ...names) {
  return `${greeting} ${names.join(", ")}!`;
}

console.log(introduce("Hello", "Alice", "Bob", "Charlie"));
// "Hello Alice, Bob, Charlie!"

Higher-Order Functions

Functions that take or return other functions:

// Function that returns a function
function multiplier(factor) {
  return function(number) {
    return number * factor;
  };
}

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

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

// Function that takes a function
function repeat(n, action) {
  for (let i = 0; i < n; i++) {
    action(i);
  }
}

repeat(3, (i) => console.log(`Iteration ${i}`));

🔍 Arrow Functions vs Regular Functions

Arrow functions don't have their own this:

const obj = {
  name: "Alice",
  regularFunc: function() {
    console.log(this.name);  // "Alice"
  },
  arrowFunc: () => {
    console.log(this.name);  // undefined (inherits from parent scope)
  }
};

✓ Best Practices

  • • Use arrow functions for callbacks and short functions
  • • Use function declarations for complex, named functions
  • • Keep functions small and focused (single responsibility)
  • • Use descriptive names that explain what the function does
  • • Avoid deeply nested functions (extract to separate functions)