JS

Functions

JavaScript · 9 entries

Function Declaration

syntax
function name(params) { ... }
example
function calculateTip(bill, tipPercent = 18) {
  return +(bill * tipPercent / 100).toFixed(2);
}
console.log(calculateTip(85));     // 15.3
console.log(calculateTip(85, 20)); // 17

Note Declarations are hoisted -- they can be called before they appear in code. This is the only function form that hoists.

Arrow Functions

syntax
const fn = (params) => expression;
const fn = (params) => { ... };
example
const double = n => n * 2;
console.log(double(7)); // 14

const greet = (name, greeting = "Hello") => `${greeting}, ${name}!`;
console.log(greet("Ava")); // "Hello, Ava!"

// Return an object literal (wrap in parentheses)
const makeUser = (name, id) => ({ name, id });
console.log(makeUser("Bo", 1));

Note Arrow functions have no own this, arguments, or super. They inherit this from the surrounding scope, making them unsuitable as object methods or constructors.

Default Parameters

syntax
function fn(param = defaultValue) {}
example
function fetchData(url, options = {}) {
  const { method = "GET", timeout = 3000 } = options;
  console.log(`${method} ${url} (timeout: ${timeout}ms)`);
}
fetchData("/api/users");
fetchData("/api/users", { method: "POST" });
output
"GET /api/users (timeout: 3000ms)"
"POST /api/users (timeout: 3000ms)"

Note Defaults are evaluated at call time, not definition time. Each call creates a fresh default value, so objects/arrays as defaults are safe.

Rest Parameters in Functions

syntax
function fn(first, ...rest) {}
example
function logTagged(level, ...messages) {
  const timestamp = new Date().toISOString();
  console.log(`[${level}] ${timestamp}:`, ...messages);
}
logTagged("INFO", "Server started", "on port 3000");
output
[INFO] 2026-04-04T...: Server started on port 3000

Note Rest parameters collect remaining arguments into a real Array. Unlike arguments, they work in arrow functions too.

Closures

syntax
function outer() {
  let state = value;
  return function inner() { /* access state */ };
}
example
function createCounter(initial = 0) {
  let count = initial;
  return {
    increment() { return ++count; },
    decrement() { return --count; },
    value()     { return count; },
  };
}
const counter = createCounter(10);
console.log(counter.increment()); // 11
console.log(counter.increment()); // 12
console.log(counter.value());     // 12

Note A closure is a function that retains access to its outer scope's variables even after the outer function has returned. Fundamental for data privacy and stateful functions.

IIFE (Immediately Invoked Function Expression)

syntax
(function() { ... })();
(() => { ... })();
example
const api = (() => {
  let requestCount = 0;
  return {
    fetch(url) {
      requestCount++;
      console.log(`Request #${requestCount}: ${url}`);
    },
    getCount() { return requestCount; }
  };
})();
api.fetch("/users");
console.log(api.getCount());
output
"Request #1: /users"
1

Note IIFEs were essential before modules for avoiding global scope pollution. Still useful for one-time initialization blocks.

Generator Functions

syntax
function* name() { yield value; }
example
function* idGenerator(start = 1) {
  let id = start;
  while (true) {
    yield id++;
  }
}
const ids = idGenerator(100);
console.log(ids.next().value); // 100
console.log(ids.next().value); // 101
console.log(ids.next().value); // 102

Note Generators are lazy -- they produce values on demand. Execution pauses at each yield and resumes when next() is called.

Async Generator Functions

syntax
async function* name() { yield await value; }
example
async function* fetchPages(baseUrl, maxPages = 3) {
  for (let page = 1; page <= maxPages; page++) {
    const res = await fetch(`${baseUrl}?page=${page}`);
    yield await res.json();
  }
}

// Usage
for await (const pageData of fetchPages("/api/posts")) {
  console.log(`Got ${pageData.items.length} items`);
}

Note Consume with for-await-of. Ideal for paginated APIs, streaming data, or any sequence of async operations.

Higher-Order Functions

syntax
function fn(callback) { callback(); }
function fn() { return function() {}; }
example
function withLogging(fn) {
  return function(...args) {
    console.log(`Calling ${fn.name} with`, args);
    const result = fn(...args);
    console.log(`Result:`, result);
    return result;
  };
}

const add = (a, b) => a + b;
const loggedAdd = withLogging(add);
loggedAdd(3, 4);
output
"Calling add with [3, 4]"
"Result: 7"

Note Functions that accept or return other functions. The backbone of functional patterns like decorators, middleware, and composition.