JavaScript Default Parameter Initializers Explained
Default parameter initializers in JavaScript allow function
parameters to be set to predetermined values if no argument or
undefined is passed during invocation. Introduced in
ECMAScript 2015 (ES6), this feature simplifies function signatures and
eliminates the need for manual fallback checks within function bodies.
This article explains what default parameter initializers are, the rules
governing when and how they are evaluated, and common patterns
associated with their use.
What Are Default Parameter Initializers?
In JavaScript, function parameters default to undefined.
Default parameter initializers allow you to assign a fallback value
directly in the function signature using the assignment operator
(=).
function greet(name = "Guest") {
return `Hello, ${name}!`;
}
console.log(greet("Alice")); // Output: Hello, Alice!
console.log(greet()); // Output: Hello, Guest!
console.log(greet(undefined)); // Output: Hello, Guest!The undefined Rule
A default initializer is triggered only when an
argument is omitted or explicitly passed as undefined.
Passing any other falsy value—such as null,
false, 0, or ""—will not trigger
the default value.
function displayCount(count = 10) {
return count;
}
console.log(displayCount(null)); // Output: null
console.log(displayCount(0)); // Output: 0
console.log(displayCount()); // Output: 10When Are Default Initializers Evaluated?
Default parameter initializers are evaluated at call time (runtime), not at the time the function is defined or parsed.
Because they are evaluated dynamically each time the function is called without that parameter: - A new instance or evaluation occurs on every relevant function call. - Initializers can execute expressions, call other functions, or instantiate new objects.
let counter = 0;
function getNextId() {
return ++counter;
}
function createUser(id = getNextId()) {
return { id };
}
console.log(createUser()); // Output: { id: 1 }
console.log(createUser()); // Output: { id: 2 }
console.log(createUser(99)); // Output: { id: 99 } (getNextId is not called)In the example above, getNextId() is only executed when
createUser is called without an argument.
Evaluation Order and Parameter Scope
Default parameters are evaluated sequentially from left to right. This behavior creates specific scope and ordering rules:
1. Referencing Preceding Parameters
Parameters to the right can reference parameters declared to their left:
function buildRectangle(width, height = width * 2) {
return { width, height };
}
console.log(buildRectangle(5)); // Output: { width: 5, height: 10 }2. Temporal Dead Zone (TDZ)
A parameter cannot reference another parameter declared to its right.
Attempting to do so results in a ReferenceError due to the
Temporal Dead Zone:
// Throws ReferenceError: Cannot access 'b' before initialization
function invalidScope(a = b, b = 2) {
return a + b;
}
invalidScope();3. Separate Parameter Scope
When a function uses default parameters, an intermediate scope is
created between the outer scope and the function’s internal body scope.
Variables declared inside the function body with let,
const, or var are not accessible inside
default parameter expressions.
const value = "outer";
function testScope(param = value) {
let value = "inner";
return param;
}
console.log(testScope()); // Output: "outer"Key Takeaways
- Trigger Condition: Default values apply only when
an argument is missing or explicitly passed as
undefined. - Runtime Execution: Initializers execute at function call time, not function definition time.
- Left-to-Right Order: Parameters are evaluated from left to right, allowing later parameters to depend on earlier ones.
- Isolated Scope: Default parameters execute within their own parameter scope, separate from the function body scope.