Skip to content

Functions

Scope: declarations, arrow functions, parameters, and callbacks. All examples were run with Node v24.

Declarations

function add(a, b) {
  return a + b;
}
console.log(add(2, 3));  // 5

No types on parameters or returns — JavaScript figures it out at runtime (and sometimes gets it wrong; that's the tradeoff).

Default parameters

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

Rest parameters: any number of arguments

function sum(...nums) {
  return nums.reduce((total, n) => total + n, 0);
}
sum(1, 2, 3);  // 6

...nums collects extra arguments into an array.

Arrow functions

const double = (x) => x * 2;
const add = (a, b) => a + b;
const greet = (name) => {
  const msg = `Hello, ${name}!`;
  return msg;
};
  • One expression: the braces and return vanish, the value is returned automatically.
  • Multiple statements: keep the braces and return.

Arrows are the modern default for short functions and callbacks. Use function for top-level named functions — it reads better.

The this gotcha (arrows vs function)

Regular functions get their own this (which changes depending on how they're called — a notorious source of bugs). Arrow functions inherit this from where they're written. Rule of thumb: use arrows for callbacks, and you'll dodge 90% of this confusion. Full this semantics are beyond these guides' scope — reach for them only when a bug forces you to.

Callbacks: functions as arguments

const nums = [1, 2, 3, 4];
const doubled = nums.map((n) => n * 2);      // [2, 4, 6, 8]
const evens = nums.filter((n) => n % 2 === 0);  // [2, 4]

Passing small functions into map/filter/forEach is the bread and butter of JavaScript. The array methods to know:

Method Does what
map Transforms each element, returns a new array
filter Keeps elements that pass the test
find First element that passes the test
forEach Runs the function on each (returns nothing)
reduce Boils the array down to one value

These return new arrays — they don't modify the original (forEach aside, which is for side effects).

Closures

function makeCounter() {
  let count = 0;
  return () => ++count;
}
const counter = makeCounter();
counter();  // 1
counter();  // 2

The returned arrow "remembers" count from where it was created. That's a closure — functions carrying their birth environment with them. You'll use this pattern for handlers, timers, and private state.

Check

  • [ ] You can write declaration, arrow, and callback forms
  • [ ] You know when braces/return can be dropped from an arrow
  • [ ] You can map/filter an array from memory

Next: Async JavaScript.