arguments

Exposes every argument passed to a non-arrow function as an array-like object.

Signature
arguments[index]
arguments.length
  • Added in JavaScript ECMAScript 1 (1997)

Return value

Arguments (array-like object)An array-like object holding the values of the arguments the current non-arrow function was called with, indexed from 0.

Errors

Referencing arguments inside an arrow function throws a ReferenceError when no enclosing non-arrow function supplies one; arguments.callee and arguments.caller throw a TypeError in strict mode.

Changelog

  • PHP ECMAScript 5 (2009)In strict mode arguments no longer stays in sync with the named parameters, and arguments.callee throws a TypeError.
  • PHP ECMAScript 2015Any function using default, rest or destructured parameters gets an unmapped arguments object even in non-strict mode, so the index-to-parameter syncing does not apply.
  • PHP ECMAScript 2015arguments gained Symbol.iterator, so for…of and spread work on it directly. Arrow functions have no arguments binding at all.

arguments is a local binding created inside every non-arrow function, holding whatever was actually passed — including arguments the function never declared.

When to reach for it

Rarely, in new code: rest parameters do the same job better. It still earns its place when you must distinguish an argument was omitted from undefined was passed explicitly (compare arguments.length), when maintaining code that predates ES2015, or when a transparent wrapper must forward everything without declaring anything.

What trips people up

It is array-like, not an array. It has length and numeric indices but none of map, filter or reduce — calling them gives TypeError: arguments.map is not a function. Convert first with Array.from(arguments) or [...arguments].

Arrow functions have no arguments. Referring to it inside one reaches the enclosing function's object, or throws a ReferenceError at the top level. This bites when converting a function expression to an arrow.

Non-strict aliasing. In a sloppy function with only simple parameters, writing arguments[0] also changes the first named parameter. Strict mode, and any function using defaults or rest, breaks that link.

Example

Try it yourself
Loading editor…
Press Run to execute the code.

When to use it

  • Tell an omitted argument apart from an explicitly passed undefined
  • Forward every argument through a logging or timing wrapper unchanged
  • Maintain a pre-ES2015 variadic function without rewriting its signature
  • Count how many arguments a call actually supplied, regardless of the signature

Frequently asked questions

Why does arguments.map throw "is not a function"?

Because arguments is an array-like object, not an array — it has length and numeric indices but does not inherit Array.prototype. Convert it first with [...arguments] or Array.from(arguments), or better, declare a rest parameter.

How do I get arguments in an arrow function?

You cannot: arrow functions have no arguments binding, and referring to it resolves to the enclosing function's object or throws a ReferenceError. Use a rest parameter — const f = (...args) => args — which is the recommended approach for any function.

Should I use arguments or rest parameters?

Use rest parameters in all new code: they give a real array, work in arrow functions, and only collect the arguments you did not name. Keep arguments when you need to know whether a parameter was omitted at all, which arguments.length answers and a rest parameter cannot.

More examples

Rest parameters do it better

Both functions produce [2, 4, 6], but the rest parameter is already a real array so no slice dance is needed. The last call shows the error people actually hit: arguments is array-like, so array methods are simply absent.

Example · javascript
function oldStyle() {
  const rest = Array.prototype.slice.call(arguments, 1);
  return rest.map((n) => n * 2);
}
function newStyle(first, ...rest) {
  return rest.map((n) => n * 2);
}
console.log(oldStyle("skip", 1, 2, 3));
console.log(newStyle("skip", 1, 2, 3));

function noMap() {
  try { return arguments.map((x) => x); }
  catch (e) { return e.constructor.name + ": arguments has no map"; }
}
console.log(noMap(1));

Non-strict aliasing between arguments and parameters

In the non-strict function the arguments object is mapped to the parameters, so writing arguments[0] also changes a and the result is 99. Strict mode unmaps it and returns 10, and so does any function with a default, rest or destructured parameter, even outside strict mode.

Example · javascript
// Function() bodies are non-strict regardless of surrounding code
const sloppy = new Function("a", "arguments[0] = 99; return a;");
console.log("non-strict:", sloppy(10));

function strictFn(a) {
  "use strict";
  arguments[0] = 99;
  return a;
}
console.log("strict:", strictFn(10));

function withDefault(a = 1) {
  arguments[0] = 99;
  return a;
}
console.log("has a default:", withDefault(10));

Discussion

  • Be the first to comment on this lesson.