cf.completefrontendCode editorOpen lab
THE JAVASCRIPT FIELD GUIDE

Default & rest parameters

Handle missing JavaScript arguments, collect any number of inputs, understand the old arguments object, spread arrays into calls, and design flexible functions.

By the end, you can
  • 01
    Choose safe defaultsKnow exactly when a default parameter runs, including undefined, null, and 0.
  • 02
    Collect many argumentsUse rest parameters instead of the old arguments object for new code.
  • 03
    Unpack arrays into callsUse spread for calls like Math.max(...scores) and for fixed-plus-many arguments.

The parameter toolbox

A parameter is the named input in a function declaration. An argument is the value you pass when you call it. You met that distinction in Declaring & calling functions. This lesson adds the tools that make function inputs pleasant in real programs.

JavaScript is forgiving: a missing argument becomes undefined, and extra arguments are usually ignored. That flexibility is useful, but it can make functions vague unless you choose a clear pattern:

  • Default parameters fill in a value when an argument is missing.
  • Rest parameters gather any number of arguments into a real array.
  • Spread in a call does the opposite: it unpacks an array into separate arguments.
  • The arguments object is the older way to see everything that was passed.
  • Options objects help you simulate overloading without pretending JavaScript has overloaded signatures.
Real-life analogyA default is a pre-filled form field

Picture an address form where the country field is already filled in. If you do nothing, the form uses that value. If you type something—even something odd—the typed value wins. A default parameter works the same way.

In real life: A form shows Country: United States
In JavaScript: function ship(country = "United States")
In real life: Leave it blank and the form uses the pre-fill
In JavaScript: Call with no argument or undefined
In real life: Type Canada and the form uses Canada
In JavaScript: Pass "Canada"; the default is skipped
In real life: Type 0 by mistake and the form still records 0
In JavaScript: Pass 0; defaults do not judge whether it is useful

Where the analogy stops: A real form might treat an empty field as missing. JavaScript parameter defaults are stricter: only a missing argument or the value undefined triggers them.

Keep one rule in your head as we start: defaults handle missing arguments, not every value that feels empty. That is different from some uses of || you may have seen, and it pairs nicely with the Nullish coalescing lesson’s idea of being precise about absence.

Default parameters

STEP THROUGH

A default parameter places = value right in the function header. It reads like a promise: “if the caller does not give me this value, use this one.”

The basic shapePop out in the code editor (opens in a new tab)JavaScript
function greet(name = "friend") {
  return "Hello, " + name;
}

greet();        // "Hello, friend"
greet("Ada");  // "Hello, Ada"

The exact trigger matters. Step through this real run and switch the call on line 5. Notice that null and 0 do not mean “use the default.”

When does the default run?
Step 0 of 4Ready
Your turn: follow the blue line

Change the call on line 5. Predict whether the default runs before you step.

Running in
  1. script
Next: line 5
Click the blue line to take the next stepPop out in the code editor (opens in a new tab)JavaScript
function greet(name = "friend") {  const message = "Hello, " + name;  console.log(message);}
CallStoreChangeResultRun = next line. Ran = already executed.
Recent returnsNothing yet. Start with the blue line.
Change the call on line 5

Changing the call starts a fresh replay. Predict the printed line first.

A guided replay recorded from real JavaScript calls, not an engine debugger. Step follows executed statements; Back reviews a snapshot. Reset starts a fresh run.
Default parameters and ?? are cousins, not twins

A parameter default runs when the argument is missing or exactly undefined. The ?? operator checks for null or undefined inside an expression. The ideas are related, but they are not interchangeable.

Later defaults can use earlier parameters because JavaScript fills them from left to right. This is handy for paired values:

Later defaults can read earlier parametersPop out in the code editor (opens in a new tab)JavaScript
function box(width, height = width) {
  return width + " × " + height;
}

box(5);     // "5 × 5"
box(5, 2);  // "5 × 2"

The pitfall is putting a default before a required-looking parameter: function label(prefix = "Item", text) { ... }. A call like label("Save") fills prefix, not text. Prefer required inputs first, defaults after them, or use an options object when there are several optional pieces.

Defaults run at call time

STEP THROUGH

A default expression is evaluated when the function is called, not once when the function is created. That means Date.now() would get a fresh time, and [] creates a fresh array for that call.

A fresh default for each call
Step 0 of 8Ready
Your turn: follow the blue line

Step through two calls. Watch the default array get made fresh each time.

Running in
  1. script
Next: line 5
Click the blue line to take the next stepPop out in the code editor (opens in a new tab)JavaScript
function remember(item, list = []) {  list.push(item);  console.log(list.join(","));}remember("cake");
CallStoreChangeResultRun = next line. Ran = already executed.
Recent returnsNothing yet. Start with the blue line.
A guided replay recorded from real JavaScript calls, not an engine debugger. Step follows executed statements; Back reviews a snapshot. Reset starts a fresh run.

This is good news. In some languages a default array can become shared state by accident. In JavaScript, list = [] inside the parameter list is made again for every call that needs it.

A tiny caution

A fresh default does not mean every value you touch is private forever. If the caller passes an existing array, your function receives that actual array. Defaults only decide what to use when the caller leaves the argument out.

Rest parameters

INTERACTIVE

Sometimes one function should accept any number of values: zero scores, three tags, five names, however many the caller has. A rest parameter uses three dots before the final parameter name:

Choose how many numbers to pass
Rest parameterPop out in the code editor (opens in a new tab)JavaScript
function sum(...numbers) {  let total = 0;  for (const number of numbers) {    total = total + number;  }  return total;}
Run result2 arguments

Call: sum(4, 8)

numbers array: [4, 8]

Array.isArray(numbers): true

Returned total: 12

Try it yourself

The rest parameter creates numbers = [4, 8]. It is a real array, so its length is 2. The function returns 12.

Rest gathers every argument after the fixed parameters. Here there are no fixed parameters, so it gathers all of them.

The rest parameter must be last. JavaScript needs every argument after the fixed parameters to go into that one array, so there cannot be another parameter after it.

Valid and invalid rest parametersPop out in the code editor (opens in a new tab)JavaScript
function log(level, ...messages) {  // ✅ rest is last
  return messages.length;
}

function bad(...items, last) {        // ❌ SyntaxError
  return last;
}
Real-life analogyRest is the miscellaneous bag

Imagine packing for a picnic. One sandwich goes in your hand because it has a special job. Every other loose snack gets swept into a “misc” bag. Rest parameters do that for arguments.

In real life: Pack the first item in your hand
In JavaScript: A fixed parameter like level
In real life: Sweep every remaining item into the bag
In JavaScript: ...messages gathers the rest
In real life: Look inside the bag and count items
In JavaScript: Use array tools like .length, .map, or for...of

Where the analogy stops: A real bag can hold anything from anywhere. A rest parameter only gathers arguments from this one function call, and it must be the final parameter.

Because rest gives you a real array, the for...of loop you learned earlier fits perfectly. Arrays get their full treatment in Stage 3, but for now it is enough to know that a rest array has length, indexes, and array methods.

The arguments object

STEP THROUGH

Before rest parameters existed, JavaScript functions used the automatic arguments object. It lists every argument passed to an old-style function body. You will see it in older code, but new code should usually choose rest.

Inspect the old arguments object
Step 0 of 6Ready
Your turn: follow the blue line

Step through the old arguments object, then compare it with rest parameters.

Running in
  1. script
Next: line 6
Click the blue line to take the next stepPop out in the code editor (opens in a new tab)JavaScript
function inspect() {  console.log(arguments.length);  console.log(arguments[0]);  console.log(Array.from(arguments).join(" | "));}
CallStoreChangeResultRun = next line. Ran = already executed.
Recent returnsNothing yet. Start with the blue line.
A guided replay recorded from real JavaScript calls, not an engine debugger. Step follows executed statements; Back reviews a snapshot. Reset starts a fresh run.
Why arguments.map failsPop out in the code editor (opens in a new tab)JavaScript
function broken() {
  return arguments.map((value) => value);
}
broken(1, 2, 3);

That snippet throws a TypeError because arguments is array-like, not a real array. Convert it first with Array.from(arguments), or better, write function broken(...values) and use values.map.

A preview for arrows

Arrow functions do not have their own arguments object. The Arrow functions lesson covers that properly; for now, it is another reason rest parameters are the modern habit.

Spread in calls

SORT

The same ... syntax has an opposite job in a function call. Rest gathers many arguments into one array. Spread unpacks one iterable value—like a simple array—into many arguments.

Real-life analogySpread unpacks the grocery bag

You cannot ask the cashier to scan a closed grocery bag. You unpack the bag onto the counter item by item. Spread does that for a function call.

In real life: A bag of apples, bread, and milk
In JavaScript: An array like scores
In real life: Put each item on the counter separately
In JavaScript: ...scores in a call
In real life: The cashier scans each item
In JavaScript: The function receives separate arguments

Where the analogy stops: Spread does not copy magic into the function. It only changes how the call is made: the function sees separate arguments, as if you typed them one by one.

Spread in callsPop out in the code editor (opens in a new tab)JavaScript
const scores = [18, 7, 21];
console.log(Math.max(...scores));
console.log(Math.max(10, ...scores, 30));
Rest and spread at a glance
QuestionRestSpread
Where it appearsFunction parameter listFunction call or array/object literal
DirectionMany arguments become one arrayOne array becomes many arguments
Examplefunction sum(...numbers) {}sum(...numbers)
Common mistakePutting another parameter after itForgetting the iterable must be unpackable
Rest or spread?
  • function sum(...numbers) { }
  • Math.max(...scores)
  • function log(level, ...messages) { }
  • send('info', ...messages)
  • greet(...names)
  • function tag(first, ...rest) { }
Try it yourself
0 of 6 correct

Sort each snippet by what the three dots are doing. Look at whether the dots are in a function header or in a call.

Choose a category for every card. You can change an answer at any time; Reset clears them all.

Simulating overloading

Some languages let you define several functions with the same name but different parameter lists. That is called overloading by signature. JavaScript does not do that. If you define the same function name twice, the later one wins.

Instead, write one function that decides what the caller meant. For small cases, branch on arguments.length, typeof, or Array.isArray. For readable real code, the modern favorite is an options object with defaults.

Options object with defaultsPop out in the code editor (opens in a new tab)JavaScript
function createUser({ name = "Anonymous", role = "viewer" } = {}) {
  return name + " (" + role + ")";
}
console.log(createUser({ name: "Ada" }));
console.log(createUser({ name: "Grace", role: "admin" }));
console.log(createUser());

The braces in the parameter gently introduce destructuring: pull the name and role properties out of the object. The Destructuring lesson later gives that syntax a full tour. The = default means createUser() is safe, and role = "viewer" fills in the missing property.

Where you’ll use this

Component props, configuration functions, loggers, formatters, and API helpers often grow optional settings. An options object keeps call sites clear: createUser({ name: "Ada", role: "admin" }) is easier to read than createUser("Ada", true, false, "admin").

Common misconceptions

“Defaults run for every falsy value.”

No. Only missing arguments and undefined trigger parameter defaults. null, 0, false, and empty strings are values the caller chose.

“Rest and spread are the same because both use three dots.”

Same punctuation, opposite jobs. Rest gathers arguments in a function header; spread unpacks values in a call.

“The arguments object is an array.”

It has indexes and length, but no array methods. Convert it or use rest parameters instead.

“Rest can appear anywhere in the parameter list.”

Rest must be last. Otherwise JavaScript could not know which arguments belong in the rest array and which belong after it.

“JavaScript picks the right function overload for me.”

JavaScript calls the function stored under that name. It does not choose by parameter types or count. Put the branching inside one function.

Practice: flexible function inputs

5 EXERCISES
Exercise 1 · Warm-upPredict when defaults apply

Predict the three printed lines. Type them separated by commas.

Starter codePop out in the code editor (opens in a new tab)JavaScript
function label(value = "empty") {
  console.log(value);
}
label(undefined);
label(null);
label(0);

Answer, then press Check. Spacing and letter case don’t matter.

    Exercise 2 · PracticeWrite average(...nums)

    Write a function that returns the average of any number of arguments. It should return 0 for no arguments.

    Starter codePop out in the code editor (opens in a new tab)JavaScript
    function average(...nums) {
      // return 0 when there are no numbers
    }

    Answer, then press Check. Spacing and letter case don’t matter.

      Exercise 3 · PracticeConvert arguments to rest

      Rewrite the function with a rest parameter, then check what listNames("Ada", "Grace") prints.

      Starter codePop out in the code editor (opens in a new tab)JavaScript
      function listNames() {
        return Array.from(arguments).join(", ");
      }

      Answer, then press Check. Spacing and letter case don’t matter.

        Exercise 4 · PracticeSpread an array into Math.min

        Use spread to print the smallest number in the array.

        Starter codePop out in the code editor (opens in a new tab)JavaScript
        const scores = [9, 4, 12];
        // print the smallest score

        Answer, then press Check. Spacing and letter case don’t matter.

          Exercise 5 · ChallengeDesign an options-object function

          Build a function that accepts { name, role } and gives both properties defaults.

          Starter codePop out in the code editor (opens in a new tab)JavaScript
          function createUser(/* options */) {
            // name defaults to "Anonymous"
            // role defaults to "viewer"
          }

          Answer, then press Check. Spacing and letter case don’t matter.

            Quiz: check your understanding

            7 QUESTIONS

            Answer from the code, not from memory. Every wrong option explains the trap.

            Lesson quiz · 7 questionsScore: first tries count
            1. Question 1 of 7When does a default parameter value run?

              Choose an answer to see the explanation.

            2. Question 2 of 7What does greet(null) print?

              Read the code, then predictPop out in the code editor (opens in a new tab)JavaScript
              function greet(name = "friend") {
                console.log("Hi " + name);
              }
              greet(null);

              Choose an answer to see the explanation.

            3. Question 3 of 7Which function header is valid JavaScript?

              Choose an answer to see the explanation.

            4. Question 4 of 7What does rest array code print?

              Read the code, then predictPop out in the code editor (opens in a new tab)JavaScript
              function count(...items) {
                console.log(Array.isArray(items));
                console.log(items.length);
              }
              count("a", "b");

              Choose an answer to see the explanation.

            5. Question 5 of 7Which statement about arguments is true?

              Choose an answer to see the explanation.

            6. Question 6 of 7What does Math.max(...scores) print?

              Read the code, then predictPop out in the code editor (opens in a new tab)JavaScript
              const scores = [3, 8, 5];
              console.log(Math.max(...scores));

              Choose an answer to see the explanation.

            7. Question 7 of 7JavaScript has no overloading by signature. What is the modern beginner-friendly workaround?

              Choose an answer to see the explanation.

            Key takeaways

            • Default parameters run only for missing arguments or undefined.
            • Default expressions are evaluated at call time, so [] is fresh for each call that needs it.
            • Rest parameters gather arguments into a real array and must be last.
            • arguments is old, array-like, and absent from arrow functions’ own scope; prefer rest.
            • Spread in calls unpacks arrays into separate arguments.
            • JavaScript simulates overloading by branching inside one function or by accepting an options object.

            Remember the one-liner.
            Defaults fill missing slots, rest gathers extra arguments, and spread unpacks a collection into a call.

            Up next: Function expressions & callbacks.

            CompleteFrontend Clear concepts. Working examples.