Default parameters: your code just got smarter

2 min read
0 views

Whether you’re building UI components, calling APIs, or writing some utility functions, it’s quite common to deal with optional function arguments. Traditionally, you’d fall back on if statements or logical ORs to assign default values. But let’s be honest, that can lead to subtle bugs.

How often have you written code like this?

function greet(name) {
  name = name || 'Guest';
  console.log(`Hello, ${name}`);
}

This old shortcut is easy to write, but it comes with a catch: it treats any falsy value as missing, including valid ones like 0 or an empty string, leading to unexpected behavior.

It’s also a bit outdated. That’s where default parameters come in, a helpful JavaScript feature that makes your functions cleaner and smarter.

What are default parameters?

Default parameters let you assign default values directly in your function signature. If a value isn’t provided or is explicitly undefined, the default is used automatically.

function greet(name = 'Guest') {
  console.log(`Hello, ${name}`);
}

Now you can do:

greet();          // Hello, Guest
greet('Kristen'); // Hello, Kristen

No need for manual checks or fallback logic inside the function body.

Beware: only undefined triggers the default

Default values apply only when a parameter is undefined, either because it was omitted or explicitly passed as undefined. Other falsy values like null, 0, or false don’t trigger the default.

function showCount(count = 10) {
  console.log(count);
}

showCount();          // 10
showCount(undefined); // 10
showCount(null);      // null (default not used)
showCount(0);         // 0

If you want to treat values like null or 0 as missing, use the nullish coalescing operator (??):

function showCount(count) {
  count = count ?? 10;
  console.log(count);
}

This ensures that only null or undefined will trigger the fallback, leaving valid values like 0 untouched.

Where you can use this IRL

Setting API options

function fetchUser(id, options = { cache: true, retries: 3 }) {
  // logic...
}

This makes your function resilient even if the caller forgets to pass an options object, while still enforcing sensible defaults.

⚠️ Note: Default parameter values are evaluated at call time. So a new object is created for options every time fetchUser is called without one. This means you’re safe from shared state issues unless you move the object outside the function and reuse or mutate it:

const defaultOptions = { cache: true, retries: 3 };

function fetchUser(id, options = defaultOptions) {
  // ⚠️ defaultOptions could be mutated and shared
}

Making utility functions flexible

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

This lets callers omit the second argument when they want to multiply by one, or just return a unchanged.

React event handlers or utility wrappers

const handleClick = (event = {}) => {
  const { target = null } = event;
  const id = event?.target?.id ?? 'default-id';
  console.log(`Clicked on element with id: ${id}`);
};

This pattern is especially helpful when event handlers are triggered in tests or wrapped in higher-order logic. Optional chaining (?.) combined with default parameters makes the code safer and more readable.

Bonus: default parameters + destructuring

Combine the power of both to handle optional config objects:

function createUser({ name = 'Anonymous', age = 24 } = {}) {
  console.log(`${name} is ${age} years old.`);
}

createUser(); // Anonymous is 24 years old.

Without default parameters, you’d have to write a lot of repetitive checks and fallbacks inside the function body. This pattern is especially useful when writing libraries, handling form inputs, or managing component props.

Extra tip: order matters

Default parameters are positional, meaning you can’t skip a parameter unless you pass undefined explicitly:

function log(a = 'A', b = 'B') {
  console.log(a, b);
}

log(undefined, 'Custom'); // A Custom
log(, 'Custom');          // ❌ SyntaxError

If you want to skip a defaulted argument, pass undefined to trigger the fallback.

Closing the loop

Default parameters are one of those small syntax upgrades that make a big difference in how you write functions. Cleaner, safer, and easier to read. What’s not to love? If you’re not using them yet, start today.

One last thing: about the arguments object

Default parameters don’t count toward the arguments object unless explicitly passed. So:

function demo(a = 1) {
  console.log(arguments.length); // 0 if no argument passed
  console.log(arguments[0]);     // undefined, even though a === 1
}

Keep in mind that arguments.length reflects the number of arguments actually passed, not including defaults, and arguments[i] may be undefined even if the parameter has a default value applied.