Portrait Dr. Axel Rauschmayer
Dr. Axel Rauschmayer
Homepage | Twitter
Cover of book “Exploring ES6”
Book, exercises, quizzes
(free to read online)
Logo of newsletter “ES.next news”
Newsletter (free)
Cover of book “JavaScript for impatient programmers”
Book (free online)

JavaScript quirk 8: array-like objects

(Ad, please don’t block)

[This post is part of a series on JavaScript quirks.]

Some objects in JavaScript look like arrays, but aren’t. They are called array-like. This blog post looks at what exactly that means and how to best work with those objects.

Array-like objects

An array-like object
  • has: indexed access to elements and the property length that tells us how many elements the object has.
  • does not have: array methods such as push, forEach and indexOf.
Two examples of array-like objects is the result of the DOM method document.getElementsByClassName() (many DOM methods return array-like objects) and the special variable arguments [1]. You can determine the number of arguments via
	arguments.length
And you can access a single argument, e.g. read the first argument:
	arguments[0]
Array methods, however, have to be borrowed. You can do that, because most of those methods are generic.

Generic methods

A generic method does not require this to be an array, it only requires this to have length and indexed element access. Normally, you invoke a method m on an array arr as follows.
	arr.m(arg0, arg1, ...)
All functions have a method call that allows you to perform the above invocation differently:
	Array.prototype.m.call(arr, arg0, arg1, ...)
The first argument of call is the value for this that m receives (in this case, arr). Because we access m directly and not via arr, we can now hand any this to that method. For example, arguments:
	Array.prototype.m.call(arguments, arg0, arg1, ...)

Examples

Let’s continue with a concrete example. The following function printArgs logs all arguments that it receives.
    function printArgs() {
        Array.prototype.forEach.call(arguments,
            function (arg, i) {
                console.log(i+'. '+arg);
            });
    }
We have used method forEach generically. printArgs in use:
    > printArgs()
    > printArgs('a')
    0. a
    > printArgs('a', 'b')
    0. a
    1. b
You can even apply generic methods to ordinary objects:
    > var obj = {};
    > Array.prototype.push.call(obj, 'a');
    1
    > obj
    { '0': 'a', length: 1 }
In the above case, property length did not exist and was automatically created, with the initial value zero.

Converting an array-like object to an array

Sometimes the best way to work with an array-like object is to convert it to an array. That can also be done via a generic method:
	Array.prototype.slice.call(arguments)
Compare: to create a copy of an array arr, you make the method call
	arr.slice()

Reference

  1. JavaScript quirk 5: parameter handling