Default parameters let you give a function parameter a fallback value that's used automatically when no argument (or undefined) is passed in for it. They were introduced in ES6 and replaced an older, more error-prone pattern that developers had been working around for years.

The Old Workaround

Before default parameters existed, developers commonly used the || operator to fake a default value:

function greetOld(name) {
  name = name || "Guest";
  return "Welcome, " + name;
}

console.log(greetOld());
console.log(greetOld("Maria"));
console.log(greetOld(0)); // bug: 0 is falsy, so it gets overridden too

Output:

Welcome, Guest
Welcome, Maria
Welcome, Guest

The bug here is subtle: greetOld(0) should arguably keep 0 as the value, but since 0 is falsy in JavaScript, the || operator overrides it anyway. This pattern breaks for any falsy-but-valid argument — 0, "", or false.

Default Parameters Syntax

Default parameters fix this by only falling back when the argument is strictly undefined — not just falsy.

function greet(name = "Guest") {
  return "Welcome, " + name;
}

console.log(greet());
console.log(greet("Maria"));
console.log(greet(0)); // 0 is a real argument, so it's used as-is

Output:

Welcome, Guest
Welcome, Maria
Welcome, 0

Defaults Can Reference Earlier Parameters

A default value can be any expression, including a reference to a parameter that came before it in the list:

function createUser(name, role = "member", displayName = name) {
  return `${displayName} (${role})`;
}

console.log(createUser("Jordan"));
console.log(createUser("Jordan", "admin"));
console.log(createUser("Jordan", "admin", "J."));

Output:

Jordan (member)
Jordan (admin)
J. (admin)

Default parameters pair naturally with destructured object parameters too, for functions that take a single "options" object — a pattern you'll run into a lot once you're comfortable with JavaScript objects. If you also need to collect an unknown number of extra arguments rather than default a missing one, that's what the rest operator is for.