Parameters in Depth
Intermediate · 18 min read · ▶ live playground · ✦ checkpoint
Your first functions had neat little blanks: name, score, bonus. Real calls are messier. Sometimes a caller leaves a blank empty, sends extra values, or wants named settings instead of memorizing the perfect order.
Default parameters
A default parameter is a fallback value JavaScript uses when the caller omits that argument or passes undefined:
function makeBadge(playerName = "Guest", mood = "ready") {
return `${playerName} is ${mood}.`;
}
console.log(makeBadge("Mina", "focused"));
console.log(makeBadge("Rae"));
console.log(makeBadge());
console.log(makeBadge(undefined, "curious"));→ Mina is focused., then Rae is ready., then Guest is ready., then Guest is curious.
Think of a default as a prefilled blank on the recipe card. If the caller brings an ingredient, JavaScript uses it. If the blank is empty, the default stays.
Defaults are especially good for optional details: a greeting style, a retry count, a starting score. They keep the function easy to call without making every caller spell out the boring case.
Rest parameters collect extra arguments
A rest parameter uses ... in the parameter list to collect all remaining arguments into an array, an ordered list-like value that gets its full lesson in Section 6:
function summarizeBonuses(playerName, ...bonuses) {
let totalBonus = 0;
for (const bonus of bonuses) {
totalBonus = totalBonus + bonus;
}
return `${playerName} earned ${totalBonus} bonus points.`;
}
console.log(summarizeBonuses("Mina", 4, 3, 2));
console.log(summarizeBonuses("Rae"));→ Mina earned 9 bonus points., then Rae earned 0 bonus points.
The rest parameter must come last, because it takes "the rest" of the arguments. playerName gets the first argument. bonuses gets every argument after that.
This is the first tiny taste of arrays. The only array facts you need here are small: rest gives you an ordered bundle, for...of can walk through it, and .length tells you how many values it holds.
Spread unpacks values at the call site
The same three dots do the opposite job in a different place. Spread at the call site means ... before an array in a function call, which unpacks that array into separate arguments:
function makeScoreLine(playerName, baseScore = 0, bonus = 0) {
return `${playerName}: ${baseScore + bonus} points`;
}
const minaRound = ["Mina", 18, 4];
const raeRound = ["Rae", 21];
console.log(makeScoreLine(...minaRound));
console.log(makeScoreLine(...raeRound));→ Mina: 22 points, then Rae: 21 points.
Same dots, two directions:
- In a parameter list,
...bonusesgathers arguments into one array. - In a call,
...minaRoundspreads one array out into arguments.
That pair matters because later you will pass function inputs around as data, then unpack them at the last responsible moment.
Try it — tune the score reporter
Run this, then change the weekendBonuses values and the practice settings. The code uses all three moves: defaults, rest, and spread.
At the › prompt, try makeScoreLine("Ari", 10, 1, 2, 3) and planPractice("Ari", { focus: "returns" }).
Options objects name the settings
Once a function has several optional settings, order becomes a memory test. Which one is minutes? Which one is focus? Did coach come before location?
An options object is an object passed as one argument to group named settings, and destructuring is pulling named pieces out of that object into parameter names:
function planPractice(
playerName,
{ minutes = 30, focus = "fundamentals", coach = "Ada" } = {},
) {
return `${playerName}: ${minutes} minutes of ${focus} with ${coach}.`;
}
console.log(planPractice("Mina", { focus: "serves", minutes: 45 }));
console.log(planPractice("Rae", { coach: "Dev" }));
console.log(planPractice("Ari"));→ Mina: 45 minutes of serves with Ada., then Rae: 30 minutes of fundamentals with Dev., then Ari: 30 minutes of fundamentals with Ada.
This shape reads well at the call site because each setting labels itself. The = {} after the options parameter keeps the whole options object optional, and the defaults inside keep each setting optional.
Use options objects when a function has several optional knobs. Use regular positional parameters when the order is obvious, like playerName, score.
Passing objects can leak mutations
Objects are powerful because they group related data. They also bring a trap: passing an object to a function does not hand over a fresh copy.
Sometimes mutation is intended. A function named spendEnergy sounds like it changes a player record. The danger is silent mutation in a function that sounds harmless, like formatPlayer or previewRound. Until objects get their full treatment in Section 7, keep this rule close: if a function mutates an object argument, make that change obvious in the name or the surrounding code.
Checkpoint
Answer all three to mark this lesson complete
You can now shape function inputs in the ways real programs need: fallback blanks, extra values, spread-out call data, and named options. Next, those functions step into scope, the rule for where names live; hoisting, the engine's pre-run registration step; and closures, functions that remember where they were born.