arguments
Exposes every argument passed to a non-arrow function as an array-like object.
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
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.
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.
// 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