Working with Array-Like Objects in JavaScript

Some objects in JavaScript can be treated like arrays even though they are not true arrays. Consider for example node lists and the arguments object. They have a length property, can be accessed via numeric indexes, and traversed with for loops.

On this page we demonstrate and describe not only these basic array-like capabilities, but also how you can apply array methods to these objects using the function call method, and how you can convert these array-like objects to arrays using splice or the ECMAScript 6 Array.from method.

Looping Through Array-Like Objects

The following example[1] demonstrates using a for loop to assign a function to the onclick property of each member of a node list:[2]

// get list of links with 'show-hide' class
var links = document.getElementsByClassName('show-hide');

// loop through links
for (var i=0, len=links.length; i<len; i++) {
    // add click handler to each link in list
    links[i].onclick = toggleVisibility;
}

Our next example demonstrates the array-like nature of the arguments object. The addArgs function has no named arguments; instead it can accommodate any number of numeric arguments and return their sum. It does so by obtaining arguments.length and iterating through the members of the arguments object using numeric indexes:

function addArgs() {
    var val, sum = 0;
    for ( var i=0, len=arguments.length; i<len; i++ ) {
        val = arguments[i];
        if ( typeof val === 'number' ) { // 
            sum += val; // 
        }
    }
    return sum;
}

console.log( addArgs(1, 4, 9) );

Next let's see what happens if we try to further exploit these array-like capabilities by applying array methods to these objects.

Array Methods with Array-Like Objects

In our next example, we pass string arguments to a function and attempt to use the array join method to convert the arguments to a single string:

// WRONG!!!
function stringArg() {
    return arguments.join(', ');
}

// TypeError: arguments.join is not a function
console.log( stringArg('Jon', 'Kara', 'Mia') ); 

We try to invoke the function and display its output using console.log. But the result is a TypeError. We could use a for loop on the arguments to concatenate a string, but there is an easier way, using the call method:

// invoke array method on arguments object using call method
function stringArg() {
    return Array.prototype.join.call( arguments, ', ');
}
console.log( stringArg('Jon', 'Kara', 'Mia') ); // Jon, Kara, Mia 

This revised function returns a string that we can display with console.log. Read on to find out how and why this works.

Using the call Method

When we invoke an array method on the arguments object, we get a TypeError because the arguments object is not an array. However, we can invoke array methods on array-like objects indirectly through the call method of the function object.[3]

The first argument to the call method is the object on which you would like to invoke the function. Subsequent arguments to the call method are passed to the function being invoked. So the following statement invokes the join method on the arguments object and passes the separator string (comma and space) to the join method:

// invoking the join method on the arguments object using call
Array.prototype.join.call( arguments, ', ');

How to Determine if a Variable Holds an Array

ECMAScript 5 includes an Array.isArray method which returns true or false depending upon whether the argument passed to it is an array or not:

// example variables to test with isArray
var ar = [1, 2, 3];
var obj = {'name': 'Jon', 'age': 27};

// display results of Array.isArray tests
console.log( Array.isArray(ar) ); // true
console.log( Array.isArray(obj) ); // false

This method is supported by the majority of browsers in current use. If you need to support older browsers such as Internet Explorer 8, you can you use a function defined as follows:

// isArray function for older browsers
var isArray = function(o) {
    return typeof o === 'object' && 
        Object.prototype.toString.call(o) === '[object Array]';
}

// test variables with isArray
console.log( isArray(ar) ); // true
console.log( isArray(obj) ); // false

How to Convert Array-Like to Array

If you wish to convert an array-like object to an array for use with array methods, you can use one of the following approaches: use the array slice method in conjuction with call, or use the ECMAScript 6 Array.from method.[4] We will use the following list of links to demonstrate:

<div class="side_links">
    <ul>
        <li><a href="#byId">getElementById</a></li>
        <li><a href="#byTag">getElementsByTagName</a></li>
        <li><a href="#byClass">getElementsByClassName</a></li>
        <li><a href="#sel">querySelectorAll</a></li>
    </ul>
</div>

First we will demonstrate the slice/call approach. We start by using document.querySelectorAll to get a node list containing the links. Then we use call to apply the array slice method to the node list. We assign the result to a variable, and since this variable is an array, we can invoke array methods on it directly, as we demonstrate here with forEach:

// get node list of links
var list = document.querySelectorAll('.side_links li a');

// convert to array using slice and call
var ar = Array.prototype.slice.call( list );

// then can use array methods
ar.forEach( function(v) {
    v.onclick = function(e) { 
        console.log( e.target.innerHTML ); 
        return false; 
    }
} );

Next we demonstrate the Array.from method of conversion. We pass the result of querySelectorAll to Array.from and assign the result to a variable. We can then use array methods on the resulting array, as we demonstrate here with the ECMAScript 5 every method:

// pass result of querySelectorAll to Array.from
var ar = Array.from( document.querySelectorAll('.side_links li a') );
// display result of applying every method to ar
console.log( ar.every( function(v) { return v.hash } ) ); // true

Back to top


  1. View the example in action. It is part of our tutorial on Obtaining Element References. ^
  2. Node lists contain references to elements. They are returned by methods for obtaining references such as getElementsByTagName, getElementsByClassName, and querySelectorAll. (See our tutorial on Obtaining Element References.) HTMLCollections are similar lists referenced by the document.forms and elements collections. (See our tutorial on Form Element References.) ^
  3. As you may know, virtually everything in JavaScript is an object, even functions. So functions can have properties and methods, like the call method. The call method invokes a function as if it were a method of another object. ^
  4. Internet Explorer (even version 11) does not support this method, but other current browsers do. ^