JavaScript Default Function Parameters Explained

In JavaScript, default function parameters allow you to initialize named parameters with default values if no value or undefined is passed into the function. Introduced in ECMAScript 2016 (ES6), this feature simplifies function definitions, eliminates the need for manual fallback checks inside function bodies, and handles missing arguments predictably.

Basic Syntax

To set a default parameter, assign a value directly to the parameter in the function declaration using the assignment operator (=):

function greet(name = 'Guest') {
    return `Hello, ${name}!`;
}

console.log(greet('Alice')); // "Hello, Alice!"
console.log(greet());        // "Hello, Guest!"

When Default Values Trigger

A default parameter is only triggered in two scenarios: 1. The argument is omitted entirely during the function call. 2. The argument is explicitly passed as undefined.

If any other value is passed—including falsy values like null, false, 0, NaN, or an empty string ""—JavaScript treats it as a valid, defined argument and will not use the default value:

function displayStatus(status = 'active') {
    return status;
}

console.log(displayStatus(undefined)); // "active" (triggers default)
console.log(displayStatus(null));      // null (does NOT trigger default)
console.log(displayStatus(''));        // "" (does NOT trigger default)

Evaluated at Call Time

Default parameter values are not evaluated when the function is defined; they are evaluated at runtime when the function is executed. This means a new instance of the default expression is computed each time the function is called without that argument:

function appendItem(item, list = []) {
    list.push(item);
    return list;
}

console.log(appendItem('A')); // ['A']
console.log(appendItem('B')); // ['B'] (a new array is created, not reused)

You can also assign function calls or complex expressions as default values:

function generateId() {
    return Math.floor(Math.random() * 1000);
}

function createUser(name, id = generateId()) {
    return { name, id };
}

Referencing Earlier Parameters

Parameters are evaluated from left to right. Therefore, a default parameter can reference preceding parameters that have already been declared:

function calculatePrice(price, tax = price * 0.1, discount = 0) {
    return price + tax - discount;
}

console.log(calculatePrice(100)); // 110

However, referencing a parameter that is defined later in the parameter list will throw a ReferenceError due to the Temporal Dead Zone (TDZ):

// This will throw a ReferenceError
function invalidFunction(a = b, b = 5) {
    return a + b;
}

Destructured Default Parameters

Default parameters can be combined with object destructuring, which is common when dealing with configuration or options objects:

function setupCanvas({ width = 300, height = 150, color = 'black' } = {}) {
    return `Canvas: ${width}x${height}, Color: ${color}`;
}

console.log(setupCanvas({ width: 500 })); // "Canvas: 500x150, Color: black"
console.log(setupCanvas());              // "Canvas: 300x150, Color: black"

In this pattern, the outer = {} allows the function to be called without arguments, while the inner defaults handle missing properties inside the object.