Skip to main content

What is arguments pseudo-Array in JavaScript

arguments is a function-local object in regular (non-arrow) JavaScript functions that automatically collects all passed arguments into an indexed, array-like structure.

Theory

TL;DR

  • Like a cashier's bag that collects everything handed over, even extras you never named
  • Array-like (has indices + length) but is an Object, not an Array - no .map() or .forEach()
  • In strict mode, the live link between arguments[i] and named params is disabled
  • Arrow functions don't have their own arguments; they inherit from the outer scope
  • Decision: use rest params (...args) in all new code; arguments only for legacy or IE11 contexts

Quick example

javascript
function greet(name, age) { console.log(arguments[0]); // "Alice" - access by index console.log(arguments.length); // 3 - counts all, even extras console.log(Array.isArray(arguments)); // false - not a real Array } greet("Alice", 30, "NYC");

Three arguments were passed but only two were declared. arguments.length shows 3 - it captures everything, not just the named ones.

Key difference

arguments works like an array for basic access (arguments[0], arguments.length) but is an Object without Array prototype methods. Calling arguments.forEach(...) throws a TypeError. To use array operations, convert first: Array.from(arguments) or [...arguments]. The design saves memory for simple indexed lookups but adds an extra step when you need filtering or mapping.

When to use

  • Legacy browser support (IE11 or untranspiled environments): arguments works without polyfills
  • Quick debug logging: console.log(arguments) shows all inputs in one call
  • Dynamic argument count in older utility code that predates rest params
  • New code: always reach for ...args; it gives a real Array with no conversion needed

How the engine handles this

In V8 (Chrome and Node.js), when a regular function executes, the engine creates an Arguments exotic object on the call stack. In non-strict mode, it maps arguments[i] directly to the corresponding named parameter through a hidden parameter map with getters and setters. Change a inside the function and arguments[0] updates too. Strict mode disables this link entirely - named params and arguments[i] become independent copies. Arrow functions skip arguments creation and inherit from the enclosing scope.

Common mistakes

Calling array methods directly:

javascript
function sum() { let total = 0; arguments.forEach(x => total += x); // TypeError: arguments.forEach is not a function }

Fix: Array.from(arguments).forEach(...) or switch to rest params.

Expecting arrow functions to have arguments:

javascript
const fn = () => console.log(arguments); // ReferenceError or outer scope's arguments

Fix: const fn = (...args) => console.log(args);

Unexpected parameter aliasing in non-strict mode:

javascript
function add(a, b) { arguments[0] = 100; return a + b; // Returns 140, not 42 - a changed with arguments[0] } add(2, 40);

Changing arguments[i] also changes the named param. Adding 'use strict' breaks that link.

Strict mode confusion:

javascript
'use strict'; function fn(a) { a = 2; console.log(arguments[0]); // Still 1 - no live mapping in strict mode } fn(1);

Real-world usage

  • Express.js (pre-ES6): route handlers inspected arguments for dynamic middleware chains
  • jQuery: legacy event handlers read arguments for extra event data in plugins
  • Lodash: utility functions converted arguments internally for variadic input
  • Pre-ES6 conversion pattern: Array.prototype.slice.call(arguments) before Array.from existed
FeatureargumentsRest params (...args)
TypeObjectArray
Array methodsNo (convert first)Yes
Strict mode mappingDisabledN/A
Arrow functionsInherited, not ownYes
New codeNoYes

Follow-up questions

Q: Why isn't arguments a real Array?
A: Memory optimization. The engine skips allocating a full Array object for simple indexed access. You only convert when you need array methods.

Q: What changes in strict mode?
A: The live parameter map is disabled. Changing a named param no longer updates arguments[i], and vice versa. They are independent after the function starts.

Q: Can you use arguments in arrow functions?
A: No own arguments is created. If you reference it inside an arrow, you get the outer regular function's arguments, or a ReferenceError if there's no enclosing regular function.

Q: How to convert arguments to an array in pre-ES6 code?
A: Array.prototype.slice.call(arguments) was the standard before Array.from and spread syntax.

Q: In V8, when is the parameter map for arguments created?
A: On function entry, for non-strict regular functions. It has getters and setters linking arguments properties to parameter slots. Strict mode and arrow functions skip it to prevent aliasing bugs.

Examples

Basic: summing any number of values

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)); // 6 console.log(sum(10, 20)); // 30

No parameters declared, but the function handles any count. arguments.length drives the loop. This is the classic pattern you'll find in pre-ES6 utility libraries.

Intermediate: legacy middleware logger

javascript
// Pre-ES6 Express-style logger - still found in older codebases function logRequest() { var args = Array.from(arguments); console.log('Received ' + args.length + ' args:', args); // args[0] = path, args[1] = handler, rest = middleware fns } logRequest('/users', handler, authMiddleware, rateLimiter); // Received 4 args: ['/users', fn, fn, fn]

Array.from converts arguments to a real array before any array operations. I've seen this exact pattern in Express codebases from 2014-2016 that were never updated - it still runs, but rest params make the intent clearer.

Short Answer

Interview ready
Premium

A concise answer to help you respond confidently on this topic during an interview.

Finished reading?