Parameters & Arguments
Parameters are the names in a function's definition; arguments are the actual values passed when it's called. JavaScript is very relaxed about matching them up, and offers default values, rest parameters and destructuring to make function inputs flexible and clear.
Missing and extra arguments
JavaScript doesn't check the number of arguments. Missing ones are undefined; extra ones are ignored:
function describe(name, age) { return `${name} is ${age}`; } console.log(describe("Ana", 30)); console.log(describe("Ben")); console.log(describe("Cleo", 25, "extra"));
Ana is 30 Ben is undefined Cleo is 25
Default parameters
A default value is used when an argument is missing or explicitly undefined:
function greet(name = "friend", greeting = "Hello") { return `${greeting}, ${name}!`; } console.log(greet()); console.log(greet("Ida")); console.log(greet("Ida", "Hey")); console.log(greet(undefined, "Welcome")); console.log(greet(null));
Hello, friend! Hello, Ida! Hey, Ida! Welcome, friend! Hello, null!
Note the last line: null is a real value, so the default isn't used. Defaults can be expressions and can even refer to earlier parameters: function box(w, h = w).
Rest parameters
A parameter starting with ... collects all remaining arguments into a real array:
function sum(...numbers) { return numbers.reduce((total, n) => total + n, 0); } function tag(label, ...items) { return `${label}: ${items.join(", ")}`; } console.log(sum(1, 2, 3, 4)); console.log(sum()); console.log(tag("Fruit", "apple", "fig", "kiwi"));
10 0 Fruit: apple, fig, kiwi
The rest parameter must be last. The related spread syntax does the opposite, expanding an array into separate arguments: Math.max(...[3, 9, 2]).
The old arguments object
Regular (non-arrow) functions also have a built-in arguments object holding every argument. It's array-like but not a real array, and arrow functions don't have it. You'll see it in older code; rest parameters have replaced it.
function oldStyle() { return arguments.length; } console.log(oldStyle("a", "b", "c"));
3
Options objects
Calls with many positional arguments are hard to read — what does createUser("Ana", true, false, 3) mean? Passing a single object with named properties, and destructuring it in the parameter list, solves this:
function createUser({ name, isAdmin = false, notify = true, retries = 3 } = {}) { return `${name}: admin=${isAdmin}, notify=${notify}, retries=${retries}`; } console.log(createUser({ name: "Ana", isAdmin: true })); console.log(createUser({ name: "Ben", retries: 5 }));
Ana: admin=true, notify=true, retries=3 Ben: admin=false, notify=true, retries=5
Each option has its own default, callers can pass options in any order, and the call site documents itself. The = {} at the end lets the function be called with no argument at all. Destructuring is covered fully in lesson 33.
Arguments are passed by value — but objects are shared
Reassigning a parameter inside a function never affects the caller's variable. But if the argument is an object, the function receives a reference to the same object, so changing its contents is visible outside:
function tryToReplace(n, list) { n = 100; list = ["replaced"]; } function addItem(list) { list.push("added"); } let count = 1; const items = ["original"]; tryToReplace(count, items); console.log(count, items); addItem(items); console.log(items);
1 [ 'original' ] [ 'original', 'added' ]
Functions that change their arguments' contents can cause surprising bugs. Where practical, return a new array or object instead: return [...list, "added"].