Functions, arguments, and rest parameters

JavaScript never enforces how many arguments a function is called with — extra ones are silently dropped, missing ones become undefined — and understanding that permissiveness is what makes rest parameters and default values make sense as deliberate features, not just syntax sugar.

Beginner

3 min read

Arguments beyond what's declared are silently ignored; missing ones become undefined

function greet(name) {
  return `Hello, ${name}`;
}
 
greet("Ada", "extra", "args"); // "Hello, Ada" — extra arguments are silently dropped, no error
greet();                        // "Hello, undefined" — missing arguments become undefined, no error

Unlike many other languages, JavaScript never validates the number of arguments a function is called with against its declared parameters — calling with too many or too few is never an error at the language level. Extra arguments are simply discarded (though still technically accessible — see below); missing ones are bound to undefined. This permissiveness is a deliberate, long-standing design choice, and it's the reason default parameters and rest parameters exist as real language features rather than being unnecessary.

Default parameters: filling in the "missing means undefined" gap

function greet(name = "friend") {
  return `Hello, ${name}`;
}
 
greet();      // "Hello, friend" — undefined triggers the default
greet(null);   // "Hello, null" — null does NOT trigger the default, only undefined does

A default parameter value is used specifically when the argument is undefined (whether that's because it was omitted entirely, or explicitly passed as undefined) — not for any other falsy value. Passing null explicitly does not trigger the default, which is a genuinely easy detail to get wrong: null is a real, intentional value in JavaScript, distinct from "this argument wasn't provided," and default parameters respect that distinction precisely.

The old arguments object vs modern rest parameters

// Old way — arguments is array-LIKE, not a real array (no .map, .filter, etc. without conversion)
function sumOld() {
  let total = 0;
  for (let i = 0; i < arguments.length; i++) total += arguments[i];
  return total;
}
 
// Modern way — rest parameters collect extra args into a REAL array
function sumNew(...numbers) {
  return numbers.reduce((total, n) => total + n, 0);
}

arguments is available inside any regular (non-arrow) function and contains every argument actually passed, but it's only array-like — it has a .length and numeric indices, but none of Array.prototype's methods (.map, .filter, .reduce) work on it directly without first converting it (Array.from(arguments)). Rest parameters (...numbers) solve this cleanly: they collect the arguments into a genuine Array instance, with every array method available immediately, and they can be named meaningfully and combined with regular parameters — arguments, by contrast, is unavailable in arrow functions entirely (covered in the next lesson), one more reason rest parameters became the modern default.

Rest parameters must come last, and only one is allowed

function logEntries(timestamp, ...entries) { } // valid — timestamp first, rest collects everything else
function invalid(...entries, timestamp) { }     // SyntaxError — rest parameter must be the LAST parameter

A rest parameter collects "everything remaining," which is exactly why it can only appear once, and only as the final parameter — there's no coherent way for the language to decide what "everything after the rest parameter" would even mean. This is a straightforward syntax rule, but worth knowing explicitly rather than discovering it as a confusing error the first time a rest parameter gets placed in the middle of a parameter list by accident.

Further reading

Check your understanding

A quick comprehension check — not tracked, not graded, just for you.

1. What happens when a JavaScript function is called with more or fewer arguments than it declares?

2. When does a default parameter value actually get used?

3. What's the key advantage of rest parameters (`...args`) over the old `arguments` object?