Functions


Function Declarations: Hoisted, available before definition. Function Expressions: Assigned to a variable, not hoisted.


Function Declarations

A function declaration defines a named function. These are hoisted, meaning they are available in their scope before their actual declaration in the code.

Example 1: Basic Function Declaration

// Function to add two numbers
function add(a, b) {
  return a + b;
}

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

Explanation The add function is declared using the function keyword, followed by the function name and its parameters. It is then called to perform the addition.


Example 2: Hoisting with Function Declarations

// Calling the function before it's declared
greet(); // Output: Hello, world!

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

Explanation Even though greet() is called before its definition, the code runs without error because function declarations are hoisted to the top of their scope.


Example 3: Function with a Return Value

// Function to calculate the area of a rectangle
function calculateArea(width, height) {
  return width * height;
}

let area = calculateArea(10, 5);
console.log(area); // Output: 50

Explanation The calculateArea function returns a value using the return keyword. This returned value is then stored in the area variable.


Example 4: Function with Default Parameters

// Function with a default parameter
function sayHello(name = "Guest") {
  console.log(`Hello, ${name}!`);
}

sayHello("Alice"); // Output: Hello, Alice!
sayHello();      // Output: Hello, Guest!

Explanation The name parameter has a default value of "Guest". If the function is called without an argument, it uses this default value.


Example 5: A Function that Calls Another Function

function square(number) {
  return number * number;
}

function printSquare(num) {
  let result = square(num);
  console.log(`The square of ${num} is ${result}.`);
}

printSquare(4); // Output: The square of 4 is 16.

Explanation The printSquare function calls the square function to perform a calculation and then prints the result to the console.


Example 6: Recursive Function Declaration

// Function to calculate factorial recursively
function factorial(n) {
  if (n === 0 || n === 1) {
    return 1;
  } else {
    return n * factorial(n - 1);
  }
}

console.log(factorial(5)); // Output: 120

Explanation The factorial function calls itself with a decremented argument until it reaches the base case of 0 or 1, demonstrating recursion.


Example 7: Function with Multiple Return Statements

// Function to check if a number is positive, negative, or zero
function checkNumber(num) {
  if (num > 0) {
    return "Positive";
  } else if (num < 0) {
    return "Negative";
  } else {
    return "Zero";
  }
}

console.log(checkNumber(10)); // Output: Positive

Explanation This function uses multiple return statements within conditional blocks to provide different outputs based on the input number.


Function Expressions

A function expression defines a function as part of an expression, typically assigning it to a variable. Unlike declarations, they are not hoisted.

Example 1: Basic Function Expression

// Function expression to subtract two numbers
const subtract = function(a, b) {
  return a - b;
};

console.log(subtract(10, 4)); // Output: 6

Explanation An anonymous function is created and assigned to the subtract constant. The function is then called using this variable.


Example 2: No Hoisting with Function Expressions

// Trying to call the function expression before definition
// This will result in a ReferenceError
// multiply(2, 3);

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

Explanation Function expressions are not hoisted. You must define them before you can call them, which helps in writing more predictable code.


Example 3: Named Function Expression for Debugging

// Named function expression for easier debugging
const divide = function divideNumbers(a, b) {
  return a / b;
};

console.log(divide(20, 5)); // Output: 4

Explanation The function is named divideNumbers, which can be helpful for identifying the function in error stack traces during debugging.


Example 4: Immediately Invoked Function Expression (IIFE)

// An IIFE that executes immediately
(function() {
  console.log("This function runs immediately!");
})();

Explanation This function is defined and executed in a single step. IIFEs are useful for creating a private scope for variables.


Example 5: Function Expression as a Callback

// Using a function expression as a callback for setTimeout
setTimeout(function() {
  console.log("This message appears after 1 second.");
}, 1000);

Explanation An anonymous function is passed as an argument to setTimeout. This function will be executed after the specified delay.


Example 6: Function Expression in an Object

// A function expression as a method in an object
const calculator = {
  add: function(a, b) {
    return a + b;
  }
};

console.log(calculator.add(3, 7)); // Output: 10

Explanation The add property of the calculator object holds a function expression, making it a method of the object.


Example 7: Higher-Order Function Returning a Function Expression

// A function that returns another function
function createGreeter(greeting) {
  return function(name) {
    console.log(`${greeting}, ${name}!`);
  };
}

const sayHi = createGreeter("Hi");
sayHi("Bob"); // Output: Hi, Bob!

Explanation The createGreeter function is a higher-order function that returns a new function. This demonstrates how function expressions can be used to create closures.