Parameters & Arguments
Functions become genuinely reusable only when they can accept input. JavaScript passes that input through parameters and arguments—two terms that are often used interchangeably but mean different things. Understanding the distinction, how values are actually passed, and what happens when the counts don’t match will save you from a whole class of subtle bugs.
Parameters vs. arguments
A parameter is the named placeholder listed in a function’s definition. An argument is the actual value you supply when you call the function. Parameters live in the declaration; arguments live at the call site.
// `name` and `greeting` are parameters
function welcome(name, greeting) {
return `${greeting}, ${name}!`;
}
// "Ada" and "Hello" are arguments
console.log(welcome("Ada", "Hello"));
Output:
Hello, Ada!
Parameters are bound to arguments positionally: the first argument fills the first parameter, the second fills the second, and so on. JavaScript does not match by name, so the order you pass values in matters.
Tip: When a function needs more than three positional parameters, pass a single options object instead—
createUser({ name, role, active }). Named keys are self-documenting and immune to ordering mistakes.
Pass-by-value and pass-by-reference
JavaScript is technically always pass-by-value, but the value depends on the type. Primitives (string, number, boolean, null, undefined, symbol, bigint) are copied, so reassigning a parameter never touches the caller’s variable. Objects (including arrays and functions) copy the reference, so the parameter points at the same underlying object the caller holds.
function mutate(primitive, object) {
primitive = 99; // local copy only
object.count = 99; // mutates the shared object
object = { count: 0 }; // reassigns the local reference only
}
let n = 1;
const data = { count: 1 };
mutate(n, data);
console.log(n); // unchanged
console.log(data.count); // mutated through the reference
Output:
1
99
The takeaway: you can mutate an object passed in, but reassigning a parameter never affects the caller. If you want to avoid surprising callers, treat object parameters as read-only or clone them first with structuredClone(obj) or { ...obj }.
Too few or too many arguments
JavaScript never throws for a mismatched argument count. Missing parameters become undefined; extra arguments are simply ignored by the named parameter list.
function box(width, height) {
return { width, height };
}
console.log(box(10)); // height is undefined
console.log(box(10, 20, 30)); // 30 is ignored
Output:
{ width: 10, height: undefined }
{ width: 10, height: 20 }
Because missing arguments silently become undefined, guard against it explicitly or—better—use default parameters to supply sensible fallbacks.
The arguments object
Inside any non-arrow function, JavaScript exposes a special arguments object: an array-like collection of every argument actually passed, regardless of how many parameters were declared. This was the classic way to write variadic functions before modern syntax existed.
function sumAll() {
let total = 0;
for (let i = 0; i < arguments.length; i++) {
total += arguments[i];
}
return total;
}
console.log(sumAll(1, 2, 3, 4));
Output:
10
arguments is array-like, not a real array—it has length and indexes but lacks map, filter, and reduce. If you need array methods, convert it with Array.from(arguments) or the spread operator [...arguments].
Why arrow functions have no arguments
Arrow functions do not bind their own arguments (just as they don’t bind their own this). Referencing arguments inside an arrow reaches into the enclosing scope instead, which is rarely what you want.
const broken = () => arguments[0]; // ReferenceError in module scope
const fixed = (...args) => args[0]; // rest parameters work everywhere
console.log(fixed("ok"));
Output:
ok
In modern code, prefer rest parameters (...args) over arguments. They give you a real array, work in arrow functions, and read more clearly.
| Feature | arguments object | Rest parameters (...args) |
|---|---|---|
| Type | Array-like object | Real Array |
| Array methods | No (must convert) | Yes |
| Available in arrows | No | Yes |
| Captures all args | Yes | Only those after named params |
| Recommended today | Legacy code only | Preferred |
Best Practices
- Match arguments to parameters by position, and keep positional parameter lists short—reach for an options object beyond three.
- Treat object parameters as shared references; clone with
{ ...obj }orstructuredClonebefore mutating if the caller shouldn’t see changes. - Never rely on JavaScript to flag a wrong argument count—validate required values explicitly or use default parameters.
- Prefer rest parameters over the
argumentsobject for variadic functions; they yield a real array. - Remember arrow functions have no
arguments—use...argsinstead. - Avoid reassigning parameters; it obscures intent and does nothing useful for the caller.