Skip to main content

Functions

Function Declarations

// Function declaration (hoisted)
function greet(name) {
return `Hello, ${name}!`;
}

// Function expression
const greet2 = function (name) {
return `Hello, ${name}!`;
};

// Arrow function
const greet3 = name => `Hello, ${name}!`;
const greet4 = name => `Hello, ${name}!`; // Single param
const greet5 = () => 'Hello, World!'; // No params

Advanced Function Features

// Default parameters
function greet(name = 'World') {
return `Hello, ${name}!`;
}

// Rest parameters
function sum(...numbers) {
return numbers.reduce((a, b) => a + b, 0);
}

// Destructuring parameters
function createUser({ name, age, email }) {
return { name, age, email };
}

// Immediately Invoked Function Expression (IIFE)
(function () {
console.log('Runs immediately');
})();

Closures

function outer(x) {
return function inner(y) {
return x + y; // Access to outer scope
};
}

const addFive = outer(5);
addFive(3); // 8

Function Context & Binding

// Function context (this)
const obj = {
name: 'John',
greet: function () {
return `Hello, ${this.name}`;
},

// Arrow functions don't have their own 'this'
arrowGreet: () => {
return `Hello, ${this.name}`; // 'this' from outer scope
},
};

// Explicit binding
const greetFunc = function (greeting) {
return `${greeting}, ${this.name}!`;
};

const person = { name: 'Alice' };
greetFunc.call(person, 'Hi'); // "Hi, Alice!"
greetFunc.apply(person, ['Hey']); // "Hey, Alice!"
const boundGreet = greetFunc.bind(person);
boundGreet('Hello'); // "Hello, Alice!"

Higher-Order Functions

// Functions that take other functions as arguments
function executeOperation(a, b, operation) {
return operation(a, b);
}

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

executeOperation(5, 3, add); // 8
executeOperation(5, 3, multiply); // 15

// Functions that return functions
function createMultiplier(factor) {
return function (number) {
return number * factor;
};
}

const double = createMultiplier(2);
const triple = createMultiplier(3);
double(5); // 10
triple(5); // 15

Function Composition

// Composing functions
const compose = (f, g) => x => f(g(x));

const addOne = x => x + 1;
const multiplyByTwo = x => x * 2;

const addOneThenDouble = compose(multiplyByTwo, addOne);
addOneThenDouble(3); // 8 (3 + 1 = 4, 4 * 2 = 8)

// Pipe function (left-to-right composition)
const pipe =
(...fns) =>
value =>
fns.reduce((acc, fn) => fn(acc), value);

const result = pipe(addOne, multiplyByTwo, x => x - 1)(5); // ((5 + 1) * 2) - 1 = 11

Recursive Functions

// Simple recursion
function factorial(n) {
if (n <= 1) return 1;
return n * factorial(n - 1);
}

// Tail recursion (optimized in some environments)
function factorialTail(n, acc = 1) {
if (n <= 1) return acc;
return factorialTail(n - 1, n * acc);
}

// Tree traversal
function traverse(node, callback) {
callback(node);
if (node.children) {
node.children.forEach(child => traverse(child, callback));
}
}

Generator Functions

// Generator function
function* numberGenerator() {
let i = 0;
while (true) {
yield i++;
}
}

const gen = numberGenerator();
gen.next().value; // 0
gen.next().value; // 1
gen.next().value; // 2

// Finite generator
function* range(start, end) {
for (let i = start; i <= end; i++) {
yield i;
}
}

for (const num of range(1, 5)) {
console.log(num); // 1, 2, 3, 4, 5
}