JavaScript arguments object vs parameters: strict mode, rest, and args

How the javascript arguments object works: args javascript, javascript arguments object vs parameters, sloppy-mode aliasing, strict mode, default parameters, variadic sum, Array.from(arguments), rest parameters vs spread in calls, arrow functions and arguments, and Math.max on arrays. Snippets include short expected-output notes from Node runs.

Published

Updated

Read time 4 min read

Reviewed byDeepak Prasad

JavaScript arguments object vs parameters: strict mode, rest, and args

In JavaScript functions, parameters are the names in the definition; arguments (the values at call time) can be read from bindings like a and b, or from the legacy arguments object. People also say args javascript when they mean either that object or, more often today, a rest parameter like (...args). Modern style favors rest parameters and spread in calls; see the spread operator in JavaScript for ... in expressions versus parameter lists.

Tested on: Node.js v20.18.2. A short note after each snippet describes what you should see in the console.


Quick reference

Rest parameters (...args) are the modern replacement for almost every arguments use case: real arrays, clearer signatures, and no coupling to parameter renames.

Situation Prefer
New variadic functions ...args (real array)
Need array methods on call values Array.from(arguments) or rest
Sloppy simple parameters Know arguments[i] can alias names
ES modules / strict No live link; treat arguments as read-only history

Simple parameters and the arguments object

In non-strict functions whose parameters are only simple (no defaults, rest, or destructuring), arguments[i] and the matching parameter can stay linked until the binding is broken in spec-defined ways:

javascript
function test(a, b, c) {
  console.log("first:", a, arguments[0]);
  console.log("second:", b, arguments[1]);
  console.log("third:", c, arguments[2]);
}
test("fun", "js", "secrets");
Output

You should see 3 lines: first: fun fun, then second: js js, then third: secrets secrets.

Reassigning a parameter or an arguments index updates the paired slot:

javascript
function test(a, b, c) {
  a = "nice";
  arguments[1] = "JavaScript";
  console.log("first:", a, arguments[0]);
  console.log("second:", b, arguments[1]);
  console.log("third:", c, arguments[2]);
}
test("fun", "js", "secrets");
Output

You should see 3 lines: first: nice nice, then second: JavaScript JavaScript, then third: secrets secrets.


With "use strict", arguments holds the original passed values; mutating arguments[i] does not change the parameter (and the other way around):

javascript
function strict(a) {
  "use strict";
  arguments[0] = 99;
  return a;
}
function sloppy(a) {
  arguments[0] = 99;
  return a;
}
console.log("strict", strict(1), "sloppy", sloppy(1));
Output

You should see one line like: strict 1 sloppy 99.

ES modules are strict by default, so new javascript arguments code in import/export files follows the strict behavior.


Default parameters: arguments does not mirror defaults the same way

javascript
function f(a = 1) {
  a = 2;
  return arguments[0];
}
console.log("no arg", f());
console.log("with 10", f(10));
Output

You should see 2 lines: no arg undefined, then with 10 10.

With default parameters (and similarly with rest or destructuring parameters), treat arguments as legacy; use named parameters or ...rest instead of relying on index coupling.


Variadic sum with arguments

javascript
function sum() {
  let total = 0;
  for (let i = 0; i < arguments.length; i++) {
    total += arguments[i];
  }
  return total;
}
console.log(sum(1, 2, 3, 4, 5));
Output

You should see one line like: 15.

Turn javascript arguments into a real array when you need array methods:

javascript
function collect() {
  return Array.from(arguments);
}
console.log(collect(1, 2, 3));
Output

You should see one line like: [ 1, 2, 3 ].


Default parameter values (separate from arguments)

javascript
function hello(name = "user") {
  console.log(`Hello, ${name}!`);
}
hello();
hello("David");
Output

You should see 2 lines: Hello, user!, then Hello, David!.


Rest parameters (preferred “args” today)

javascript
function sum(...numbers) {
  let total = 0;
  for (let i = 0; i < numbers.length; i++) {
    total += numbers[i];
  }
  return total;
}
console.log(sum(...[1, 2, 3, 4, 5]));
Output

You should see one line like: 15.


Spread in a call: Math.max and arrays

Math.max expects separate numeric arguments, not one array value:

javascript
const numbers = [1, 7, 2, 9];
console.log(Math.max(numbers));
console.log(Math.max(...numbers));
Output

You should see 2 lines: NaN, then 9.

NOTE
The ... token in Math.max(...numbers) is spread (expand values into the call). In function f(...values), it is a rest parameter (collect remaining arguments into an array). Same syntax, opposite direction.

Arrow functions and arguments

Arrow functions do not define their own arguments binding. They inherit arguments from the nearest enclosing non-arrow function:

javascript
function outer() {
  const inner = () => arguments[0];
  return inner();
}
console.log(outer("fromOuter"));
Output

You should see one line like: fromOuter.

For an arrow that stands alone, use (...args) => instead of arguments.


Summary

Treat arguments as legacy: it is array-like, not an Array, and its interaction with strict mode and non-simple parameters trips readers—default to ...args in new code.

  • Parameters are declared names; arguments is a positional snapshot (array-like, not Array).
  • Strict mode and non-simple parameter lists break the old live aliasing story—prefer rest parameters.
  • Use spread when calling variadic APIs like Math.max; use rest when collecting caller inputs.
  • Arrows do not get their own arguments; use an explicit ...args parameter.

References

MDN guides for the legacy object, rest parameters, spread, and strict-mode rules.


Frequently Asked Questions

1. Is the javascript arguments object a real array?

No. It is array-like (indexed properties and length) but not an Array instance. Use Array.from(arguments) or Array.prototype.slice.call(arguments) to get a real array so you can use map, filter, and so on.

2. What is the difference between parameters and arguments?

Parameters are the names in the function declaration. Arguments are the actual values passed in a specific call. The arguments object holds those passed values by position.

3. Why does my arrow function not have args javascript style access to arguments?

Arrow functions do not have their own arguments binding. They close over the arguments of the nearest enclosing non-arrow function, if any; otherwise arguments is not defined in that scope. Prefer rest parameters (...args) on the arrow itself.

4. Does strict mode change the arguments object?

Yes. In strict mode, assignments to parameters do not update arguments indices and vice versa. Sloppy-mode functions with only simple parameters can alias parameters with arguments[i].

5. Should I use arguments or rest parameters in new code?

Prefer rest parameters. They give a real array, clearer intent, and avoid legacy coupling between parameter names and arguments indices.

6. Why is arguments[0] undefined when I use default parameters and call the function with no arguments?

With default parameters, the arguments object does not track defaults the same way named parameters do. If no argument is passed, arguments can be empty while the parameter still receives its default.
Olorunfemi Akinlua

Boasting over five years of experience in JavaScript, specializing in technical content writing and UX design. With a keen focus on programming languages, he crafts compelling content and designs …