Most of us think about the arguments “array-like” object for about one second: after we decide to use it, and before converting it to an array with Array.prototype.slice.call(arguments). While this makes working with arguments easier (as we get access to all of the Array methods), it unnecessarily complicates the true nature of the arguments object. So let’s take a step back, and take a closer look at what is actually inside the arguments object before we slice and dice.

The Basics

The first thing we want to do is forget that we ever heard “Array-like object”. When we think about arguments just like an object, we can better wrap our heads around what it is actually doing.

The arguments object is a local variable that is passed down to every function created (along with this). This means that every function you ever write will have access to it’s own arguments object. The most common use of this object is to allow for any number of arguments to passed into a function without explicitly giving parameters.

Inside the arguments object

The first thing we notice from the code above is that we iterated through the object like an array with sequential and numeric keys/indexes. The properties of arguments will give us more insight into what’s going on.

The arguments object has four additional properties aside from the indexes corresponding to the number of arguments passed into the function when it was called. These can all be accessed directly with arguments.PROPERTY_NAME. These properties are:

callee : This property gives a reference to the function that is currently executing. Within our sumAllArguments function arguments.callee would give us a reference to sumAllArguments. The return value is a just a reference.

length: This is the total number of arguments passed into our function when it was called. It is important to understand the difference between the length property that every function has and the length property of the arguments object. The length property of the actual function will return the number of parameters while the length property of the arguments object will return the number of arguments that were passed in when it was invoked.

__proto__: A good ol’ standard proto property that tells us the properties it inherits and from it’s constructor. It inherits from Object.prototype and gets to use it’s methods. No surprises here.

SymbolIterator**: This is a strange property of the arguments object that you will never need to do anything with explicitly. This property contains a function called ArrayValues. This allows for what would be an object, inheriting from Object.prototype, to operate like an array. This is how the Array function changes the standard key/value pair formula of the object into the index/value set-up of an array.

In addition to these properties, all of the arguments passed into the function at call time are allocated sequentially into the beginning of the object.

So, how does it work?

There are two keys things to remember:

Because arguments inherits the methods from the Object.prototype constructor, it can use the method propertyIsEnumerable to explicitly define what properties in the object can be iterated over. It is here that all properties except for the array index/value pairs cannot be iterated over. This is why when running a loop to access the arguments, you don’t return .length, .__proto__, or .SymbolIterator. The arguments.SymbolIterator(…) allows for the “key” for each argument to be a numeric value that increases sequentially. This allows us to access those arguments using numeric keys such as arguments[1].

Given what we now know, it should not be surprising that we can just as easily iterate through the object using a for…in loop.

Wrapping Up

In closing, I find it easier to think of arguments as a simple object before converting it into an array or some other data structure.