Ad – 728Γ—90
βš™οΈ Functions

JavaScript Function Parameters – Default, Rest, and Destructured

Parameters are the inputs to a function. JavaScript gives you rich ways to define them: positional, default values, variadic rest parameters, and destructured object/array params. Learn them all, plus the crucial pass-by-value vs pass-by-reference distinction.

⏱️ 18 min read 🎯 Beginner πŸ“… Updated 2026

Positional Parameters

Parameters are matched to arguments by position. The first argument goes to the first parameter, and so on.

JavaScript
function introduce(firstName, lastName, age) {
  return `${firstName} ${lastName}, age ${age}`;
}

console.log(introduce("Alice", "Smith", 30)); // Alice Smith, age 30
console.log(introduce("Bob", "Jones", 25));   // Bob Jones, age 25

// Extra arguments are silently ignored
console.log(introduce("Alice", "Smith", 30, "extra")); // OK

// Missing arguments become undefined
console.log(introduce("Alice")); // Alice undefined, age undefined
β–Ά Output
Alice Smith, age 30 Bob Jones, age 25 Alice Smith, age 30 Alice undefined, age undefined

Default Parameter Values

Default values are used when an argument is undefined (missing or explicitly passed as undefined).

JavaScript
function createUser(name, role = "viewer", isActive = true) {
  return { name, role, isActive };
}

console.log(createUser("Alice"));                    // {name:'Alice', role:'viewer', isActive:true}
console.log(createUser("Bob", "admin"));             // {name:'Bob', role:'admin', isActive:true}
console.log(createUser("Carol", "editor", false));   // {name:'Carol', role:'editor', isActive:false}

// Passing undefined explicitly triggers the default
console.log(createUser("Dave", undefined, false));   // {name:'Dave', role:'viewer', isActive:false}

// Passing null does NOT trigger the default
console.log(createUser("Eve", null, true));          // {name:'Eve', role:null, isActive:true}
β–Ά Output
{ name: 'Alice', role: 'viewer', isActive: true } { name: 'Bob', role: 'admin', isActive: true } { name: 'Carol', role: 'editor', isActive: false } { name: 'Dave', role: 'viewer', isActive: false } { name: 'Eve', role: null, isActive: true }
⚠️
null Does Not Trigger Default

Defaults only kick in for undefined, not null. This is because null is an intentional "empty" value, while undefined means "nothing was provided".

Rest Parameters (...args)

The rest parameter syntax ...name collects all remaining arguments into a real Array. It must be the last parameter.

JavaScript
// Variadic sum function
function sum(...numbers) {
  return numbers.reduce((acc, n) => acc + n, 0);
}

console.log(sum(1, 2, 3));          // 6
console.log(sum(1, 2, 3, 4, 5));    // 15
console.log(sum());                 // 0

// Mix: fixed params + rest
function logMessage(level, ...messages) {
  const formatted = messages.join(" ");
  console.log(`[${level.toUpperCase()}] ${formatted}`);
}

logMessage("info", "Server", "started", "on port 3000");
logMessage("error", "Connection", "refused");
β–Ά Output
6 15 0 [INFO] Server started on port 3000 [ERROR] Connection refused

The arguments Object (Legacy)

Before rest parameters existed, arguments was used to access all passed arguments. It's array-like but not a real Array, and it's unavailable in arrow functions.

JavaScript
// Legacy approach β€” avoid in modern code
function legacySum() {
  let total = 0;
  for (let i = 0; i < arguments.length; i++) {
    total += arguments[i];
  }
  return total;
}
console.log(legacySum(1, 2, 3)); // 6

// Modern rest parameter approach (preferred)
function modernSum(...nums) {
  return nums.reduce((a, b) => a + b, 0);
}
console.log(modernSum(1, 2, 3)); // 6
β–Ά Output
6 6

Destructured Parameters

You can destructure an object or array directly in the parameter list, extracting values by name.

JavaScript
// Object destructuring in parameters
function displayUser({ name, age, city = "Unknown" }) {
  console.log(`${name}, ${age} years old, from ${city}`);
}

displayUser({ name: "Alice", age: 30, city: "London" });
displayUser({ name: "Bob", age: 25 }); // city defaults to "Unknown"

// Array destructuring in parameters
function processCoords([x, y, z = 0]) {
  console.log(`x=${x}, y=${y}, z=${z}`);
}

processCoords([10, 20]);
processCoords([1, 2, 3]);
β–Ά Output
Alice, 30 years old, from London Bob, 25 years old, from Unknown x=10, y=20, z=0 x=1, y=2, z=3

Named Parameters Pattern

When a function needs many optional configuration options, pass a single options object. This is the "named parameters" pattern β€” much cleaner than many positional arguments.

JavaScript
// Hard to read: what does each argument mean?
function createButton("Submit", true, "primary", "lg", null) { /* ... */ }

// Named parameters β€” self-documenting
function createButton({ text, disabled = false, variant = "default", size = "md", icon = null } = {}) {
  return { text, disabled, variant, size, icon };
}

const btn = createButton({ text: "Submit", variant: "primary", size: "lg" });
console.log(btn);

// Can call with no args because of = {} default
const defaultBtn = createButton();
console.log(defaultBtn);
β–Ά Output
{ text: 'Submit', disabled: false, variant: 'primary', size: 'lg', icon: null } { text: undefined, disabled: false, variant: 'default', size: 'md', icon: null }

Pass by Value vs Pass by Reference

Primitives (numbers, strings, booleans) are passed by value β€” a copy is made. Objects and arrays are passed by reference β€” the function gets access to the original.

JavaScript
// Primitive β€” pass by value (copy)
function double(n) {
  n = n * 2; // Modifies local copy only
  return n;
}
let x = 5;
double(x);
console.log(x); // Still 5 β€” original unchanged

// Object β€” pass by reference
function addScore(player) {
  player.score += 10; // Modifies original!
}
const p = { name: "Alice", score: 100 };
addScore(p);
console.log(p.score); // 110 β€” original changed!

// Avoid mutation: create and return new object
function addScoreImmutable(player) {
  return { ...player, score: player.score + 10 };
}
const p2 = { name: "Bob", score: 100 };
const p2Updated = addScoreImmutable(p2);
console.log(p2.score);        // 100 β€” original safe
console.log(p2Updated.score); // 110
β–Ά Output
5 110 100 110

Callbacks as Parameters

JavaScript
// Higher-order function accepting a callback
function processItems(items, transform) {
  return items.map(transform);
}

const prices = [10, 20, 30];
const withTax = processItems(prices, price => price * 1.2);
console.log(withTax); // [12, 24, 36]

// Callback with error-first pattern (Node.js style)
function fetchData(url, onSuccess, onError) {
  if (!url) {
    onError(new Error("URL required"));
    return;
  }
  onSuccess({ data: "mock response from " + url });
}

fetchData("https://api.example.com",
  (res) => console.log("Got:", res.data),
  (err) => console.log("Error:", err.message)
);
β–Ά Output
[ 12, 24, 36 ] Got: mock response from https://api.example.com
Ad – 336Γ—280

πŸ‹οΈ Practical Exercise

Write a function formatCurrency(amount, { currency = 'USD', decimals = 2, symbol = '$' } = {}) using the named parameters pattern. It should return a string like "$1,234.56". Test it with:

  • formatCurrency(1234.5)
  • formatCurrency(1000, { currency: 'EUR', symbol: '€' })
  • formatCurrency(500, { decimals: 0 })

πŸ”₯ Challenge Exercise

Build a function pipeline(...fns) that accepts any number of functions as rest parameters and returns a new function. The returned function passes its input through all the provided functions in order (output of one becomes input of the next). Test with: pipeline(x => x * 2, x => x + 1, x => x ** 2)(3) β€” should produce 49.

πŸ“‹ Summary

  • Parameters are positional; extra arguments are ignored, missing ones are undefined.
  • Default values fill in for undefined (not null).
  • Rest parameters (...args) collect remaining arguments into a real Array.
  • Avoid the legacy arguments object β€” use rest params instead.
  • Destructured parameters let you pull values by name directly in the signature.
  • Named parameters (options object) are cleaner than many positional args.
  • Primitives are passed by value; objects/arrays are passed by reference.

Interview Questions

  • What is the difference between rest parameters and the arguments object?
  • When does a default parameter value trigger? Does null trigger a default?
  • Explain pass-by-value vs pass-by-reference with examples.
  • What is the named parameters pattern and why is it useful?
  • How do you handle optional parameters in a clean way?

Frequently Asked Questions

Can I have a default parameter before a required one?+

Technically yes, but it's unhelpful. To use the default, you must pass undefined explicitly: fn(undefined, "value"). Always place parameters with defaults after required ones.

Can rest parameters be used in arrow functions?+

Yes. Rest parameters work in all function types including arrow functions. However, the arguments object is NOT available in arrow functions β€” another reason to prefer rest params.

What is function arity?+

Arity is the number of parameters a function expects. You can check it with fn.length. Rest parameters and parameters with defaults don't count toward the length property.