How to Use Default Parameters in JS Functions
Default parameters let you set fallback values when an argument is missing or undefined. Learn the syntax, rules, and practical patterns for cleaner function signatures.
Default parameters let you set a fallback value directly in the function signature. If the caller omits an argument or passes undefined, the default takes over. No more manual typeof checks cluttering your function body.
Here is the simplest example:
function greet(name = "Guest") {
return `Hello, ${name}!`;
}
console.log(greet("Sara")); // "Hello, Sara!"
console.log(greet()); // "Hello, Guest!"The equals-Guest part of the parameter list says: if name is missing or undefined, use "Guest" instead. That is the entire feature.
Before Default Parameters
Before ES6 introduced default parameters in 2015, developers handled missing arguments manually. If you are unclear on the difference between parameters and arguments, read JS Function Parameters vs Arguments Differences first.
Before default parameters existed, the common pattern was:
function greet(name) {
name = typeof name !== "undefined" ? name : "Guest";
return `Hello, ${name}!`;
}Some developers reached for a shorter version using the logical OR operator instead, since it looks like it does the same job in fewer characters:
function greet(name) {
name = name || "Guest"; // Bug: treats "" and 0 as missing too
return `Hello, ${name}!`;
}The OR-operator approach fails when the argument is a valid falsy value like 0, an empty string, or false. Default parameters solve this correctly, since only undefined triggers the fallback.
Only undefined Triggers the Default
This is the most important rule. Default parameters activate only when the argument is strictly undefined. Other falsy values pass through unchanged. For a refresher on how functions work, see What Is a Function in JavaScript Beginner Guide.
function test(value = "default") {
console.log(value);
}
test(); // "default"
test(undefined); // "default"
test(null); // null (not default!)
test(0); // 0 (not default!)
test(""); // "" (not default!)
test(false); // false (not default!)This is deliberate. Values like null, 0, and an empty string are meaningful and might be passed on purpose, so JavaScript only falls back to the default when it sees the true absence of a value, which is exactly what undefined represents. Silently replacing a real 0 or an empty string would hide bugs instead of preventing them.
Defaults Are Evaluated at Call Time
The default expression runs fresh every time the function is called. This is especially useful for arrays and objects as defaults:
function addItem(item, list = []) {
list.push(item);
return list;
}
console.log(addItem("a")); // ["a"]
console.log(addItem("b")); // ["b"] -- fresh array, not ["a", "b"]Each call creates a new empty array. If defaults were evaluated once at definition time, every call would share the same array, which would be a subtle and painful bug.
This also means function calls used as defaults run at each invocation, not once when the function is defined. That matters whenever the default value should reflect something that changes over time, such as a timestamp:
function getTimestamp() {
return Date.now();
}
function log(message, time = getTimestamp()) {
console.log(`[${time}] ${message}`);
}
log("start");
// Wait a second...
log("end"); // Different timestampReferencing Earlier Parameters
Default parameters are not limited to fixed values. A default value can reference parameters defined to its left in the same parameter list, which lets one argument's default depend on another argument the caller already provided:
function formatName(first, last, full = `${first} ${last}`) {
return full;
}
console.log(formatName("Jane", "Doe")); // "Jane Doe"
console.log(formatName("Jane", "Doe", "JD")); // "JD" (explicit overrides default)This is powerful for computed defaults that depend on other arguments, since you can express a relationship between two parameters directly in the function signature instead of recalculating it in the function body:
function createRange(start, end = start + 10) {
return [start, end];
}
console.log(createRange(5)); // [5, 15]
console.log(createRange(5, 7)); // [5, 7]The reverse does not work. A parameter cannot reference one defined to its right, because each parameter is initialized left to right and a later parameter does not exist yet when an earlier default runs:
function broken(a = b, b = 1) {
return a + b;
}
broken(); // ReferenceError: Cannot access 'b' before initializationThe error happens because the first parameter's default tries to read the second parameter before it has been set up. Parameters share the same left-to-right initialization order as let and const declarations, including the temporal dead zone that blocks early access.
Default Parameters and the arguments Object
When you use default parameters, the arguments object stops reflecting changes to the named parameters:
function withDefaults(a, b = 2) {
console.log(arguments[0], arguments[1]);
a = 99;
console.log(arguments[0]); // Still the original value
}
withDefaults(10);
// 10 undefined
// 10 (arguments[0] is still 10, not 99)In strict mode or with default parameters, the arguments object is a snapshot of the call values, not a live view.
Defaults and function.length
Default parameters affect the function's length property, which counts the number of parameters before the first default:
function f1(a, b) {} // f1.length === 2
function f2(a, b = 1) {} // f2.length === 1
function f3(a = 1, b) {} // f3.length === 0
function f4(a, b = 1, c) {} // f4.length === 1Everything from the first default onward is excluded from the count. This matters when libraries introspect function signatures.
Practical Patterns
Optional Configuration Objects
A common pattern combines default parameters with destructuring so a function can accept an optional options object, where each option falls back to a sensible value when the caller leaves it out:
function createButton(text, { size = "md", color = "blue", disabled = false } = {}) {
console.log(`Button: "${text}", size=${size}, color=${color}, disabled=${disabled}`);
}
createButton("Submit");
// Button: "Submit", size=md, color=blue, disabled=false
createButton("Delete", { color: "red", disabled: true });
// Button: "Delete", size=md, color=red, disabled=trueThe empty-object default at the end is critical. Without it, calling createButton with only the text argument would throw a TypeError, because you cannot destructure a value that is undefined.
Required Parameter Pattern
You can use default parameters to enforce that an argument is provided:
function required(name) {
throw new Error(`Missing required parameter: ${name}`);
}
function createUser(name = required("name"), email = required("email")) {
return { name, email };
}
createUser("Alex", "alex@example.com"); // Works
createUser(); // Error: Missing required parameter: nameThis is more of a pattern than a built-in feature, but it uses default parameters creatively to simulate required arguments.
Common Mistake: Confusing null with undefined
Beginners often expect null to trigger a default value the same way a missing argument does, since both represent "nothing" in everyday language. JavaScript treats them differently: only undefined activates a default parameter.
function show(value = "default") {
console.log(value);
}
show(null); // null -- not "default"Passing null on purpose is common when clearing a value, such as resetting a selection, so the language intentionally lets it through unchanged. If you want null to also trigger the default, you need to handle it in the function body or use the ?? nullish coalescing operator:
function show(value) {
value = value ?? "default";
console.log(value);
}
show(null); // "default"Default parameters alone do not catch null.
Where to Go Next
Default parameters replace verbose undefined checks with clean, self-documenting function signatures. They are evaluated fresh at each call, can reference earlier parameters, and only activate for undefined, not for null or other falsy values. Use them to make your functions more resilient and your code easier to read.
Once defaults feel comfortable, revisit how they interact with the rest of a function's parameter list, especially when mixing required arguments, defaulted arguments, and rest parameters in the same signature. Reading real function signatures in library code becomes much easier once you can spot a default value at a glance and reason about exactly when it applies.
Rune AI
Key Insights
- Set a default with param = value directly in the function signature.
- The default only triggers when the argument is undefined, not for null, 0, or ''.
- Defaults are evaluated at call time, so each call gets a fresh array, object, or computed value.
- Earlier parameters are available to later defaults: function f(a, b = a * 2).
- Default parameters do not contribute to the function's .length property.
Frequently Asked Questions
What is the difference between passing undefined and not passing an argument?
Can I use a function call as a default value?
Do default parameters work in arrow functions?
Conclusion
Default parameters replace verbose undefined checks with clean, self-documenting function signatures. They are evaluated fresh at each call, can reference earlier parameters, and only activate for undefined -- not for null or other falsy values. Use them to make your functions more resilient and your code easier to read.
More in this topic
JavaScript While Loop Explained: A Complete Guide
A while loop repeats code as long as a condition stays true. Learn the syntax, see practical examples, and understand when a while loop is the right choice over a for loop.
JavaScript Loops Tutorial: for, while, do while
Loops let JavaScript repeat code without writing it twice. Learn the three core loop types, what each one does, and when to choose one over another.
How to Loop Through Arrays Using JS for Loops Guide
Looping through arrays is the most practical use of JavaScript for loops. Learn how to access each element by index, avoid off-by-one errors, and choose between for, for...of, and forEach.