Skip to main content

Functions

In JavaScript, functions are core building blocks. A function is a reusable block of code that performs a specific task. Functions allow for modular code, encapsulation, and are essential for asynchronous operations and callback handling.

Declaring Functions

Functions in JavaScript can be created in several ways, each with unique syntax and behavior.

Function Declaration

A function declaration defines a named function that can be invoked later.

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

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

Characteristics:

  • Function declarations are hoisted, meaning they are available throughout their scope even before they are declared.

Function Expression

A function expression creates a function as part of an expression, usually by assigning it to a variable.

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

console.log(greet("Bob")); // Output: Hello, Bob!

Characteristics:

  • Function expressions are not hoisted. The function can only be used after the expression is evaluated.

Arrow Function

An arrow function is a concise way to write functions introduced in ES6.

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

console.log(greet("Carol")); // Output: Hello, Carol!

Characteristics:

  • Arrow functions have a shorter syntax and are useful for simple functions.
  • They do not have their own this context (inherited from their enclosing scope).

Parameters and Arguments

Functions can take parameters (placeholders in the function definition) and are passed arguments when invoked.

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

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

Default Parameters: JavaScript allows you to set default values for function parameters.

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

console.log(greet()); // Output: Hello, Guest!

Return Statements

Functions use the return keyword to return a value to the caller. If there is no return, the function returns undefined by default.

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

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

Returning Functions: Functions in JavaScript can also return other functions.

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

const double = createMultiplier(2);
console.log(double(5)); // Output: 10

Anonymous Functions

Anonymous functions are functions without a name, often used as arguments or immediately invoked.

setTimeout(function () {
console.log("This message appears after 2 seconds");
}, 2000);

Immediately Invoked Function Expressions (IIFE): An IIFE is an anonymous function that is executed immediately after its definition.

(function () {
console.log("IIFE Executed!");
})();

Higher-Order Functions

A higher-order function is a function that accepts other functions as arguments or returns a function. Many built-in array methods like map, filter, and reduce are higher-order functions.

const numbers = [1, 2, 3, 4];

const doubled = numbers.map((num) => num * 2);
console.log(doubled); // Output: [2, 4, 6, 8]

Closures

A closure is created when an inner function maintains access to variables from its outer function, even after the outer function has finished execution.

function outer() {
const message = "Hello, world!";

function inner() {
console.log(message);
}

return inner;
}

const sayHello = outer();
sayHello(); // Output: Hello, world!

Closures are useful for encapsulating data and creating private variables.

this Context

The this keyword refers to the context in which a function is called. In traditional functions, this refers to the object calling the function. In arrow functions, this is lexically scoped, meaning it refers to the enclosing scope.

const person = {
name: "Alice",
greet: function () {
console.log(`Hello, ${this.name}`);
},
};

person.greet(); // Output: Hello, Alice

// With arrow function (inherits 'this' from surrounding scope)
const person2 = {
name: "Bob",
greet: () => {
console.log(`Hello, ${this.name}`);
},
};

person2.greet(); // Output: Hello, undefined (since 'this' refers to the global scope)

Function Scope and Hoisting

JavaScript functions are function-scoped (or block-scoped if using let or const within blocks). Function declarations are hoisted, meaning they can be called before their definition.

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

function add(x, y) {
return x + y;
}

Rest Parameters and Spread Operator

Rest Parameters allow a function to accept an indefinite number of arguments as an array:

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

console.log(sum(1, 2, 3, 4)); // Output: 10

Spread Operator lets you spread an array into individual arguments:

const nums = [1, 2, 3];
console.log(Math.max(...nums)); // Output: 3

Pure vs. Impure Functions

  • Pure Functions: A pure function always returns the same result for the same inputs and has no side effects.
function add(a, b) {
return a + b;
}
  • Impure Functions: Impure functions may have side effects, such as modifying global variables or changing input data.
let count = 0;
function increment() {
count++;
}