Array like objects

For historical reasons there are places in JavaScript where you end up interacting with objects that are a lot like Arrays, but technically aren't. The main difference is that they don't have Array.prototype in their prototype chain, and thus don't inherit the common array methods.

The most common one of these array like objects is 'arguments'. It gets injected into every single function scope, and contains a list of all of arguments that were passed to the function. It is super handy for doing variable argument functions. Often you will want to manipulate these arguments, and since it feels like an array you start with your familiar array stuff.

// WARNING: this doesn't work. function sum () { return arguments.reduce(function (a, b) { return a + b }) } console.log(sum(1, 2, 3)) // KABOOM

Trying to call reduce isn't going to work, because we don't have an array. Reduce isn't defined, so we get the common and frustrating 'undefined is not a function' error.

We have two options. Figure out how to work with array like objects in an acceptable way, or figure out how to convert an array like object into an array.

You can use a for loop to work with an array like object. However it's even easier to convert the object to a proper array. This has the added benefit that you are working with a copy, so you don't have to worry about mutating the original arguments object (which you want to avoid).

var slice = Array.prototype.slice function sum () { return slice.call(arguments).reduce( function (a, b) { return a + b } ) } console.log(sum(1, 2, 3)) // 6

The conventional way to do this is to use the native slice method. Since the method isn't available on Objects, we get a stand alone reference off of array, and then use the call method to apply it in the context of the arguments object. This does the default action of slice, returning us a new array that is a copy starting at the beginning and going to the end.

It looks a little cheesy, but it works most places and is pretty fast and safe. This trick works for node lists and other objects with sequential keys starting at '0' that aren't actually arrays. Why aren't they arrays you might want to ask? Well, because we can't have nice things. At least we can have nice workarounds.