What are Array-like Objects?

JavaScript has “Array-like Objects”, which are Object representations of Arrays with a length property. For example:

var realArray = ['a', 'b', 'c'];
var arrayLike = {
  0: 'a',
  1: 'b',
  2: 'c',
  length: 3
};

Common examples of Array-like Objects are the [arguments](<https://developer.mozilla.org/en/docs/Web/JavaScript/Reference/Functions/arguments>) object in functions and [HTMLCollection](<https://developer.mozilla.org/en-US/docs/Web/API/HTMLCollection>) or [NodeList](<https://developer.mozilla.org/en-US/docs/Web/API/NodeList>) objects returned from methods like [document.getElementsByTagName](<https://developer.mozilla.org/en-US/docs/Web/API/Document/getElementsByTagName>) or [document.querySelectorAll](<https://developer.mozilla.org/en-US/docs/Web/API/Document/querySelectorAll>).

However, one key difference between Arrays and Array-like Objects is that Array-like objects inherit from [Object.prototype](<https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/prototype>) instead of [Array.prototype](<https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/prototype>). This means that Array-like Objects can’t access common Array prototype methods like [forEach()](<https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/forEach>), [push()](<https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/push>), [map()](<https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/map>), [filter()](<https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/filter>), and [slice()](<https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/slice>):

var parent = document.getElementById('myDropdown');
var desiredOption = parent.querySelector('option[value="desired"]');
var domList = parent.children;

domList.indexOf(desiredOption); // Error! indexOf is not defined.
domList.forEach(function() { 
  arguments.map(/* Stuff here */) // Error! map is not defined.
}); // Error! forEach is not defined.

function func() {
  console.log(arguments);
}
func(1, 2, 3);   // → [1, 2, 3]

Convert Array-like Objects to Arrays in ES6

  1. Array.from:

    const arrayLike = {
      0: 'Value 0',
      1: 'Value 1',
      length: 2
    };
    arrayLike.forEach(value => {/* Do something */}); // Errors
    const realArray = Array.from(arrayLike);
    realArray.forEach(value => {/* Do something */}); // Works
    
  2. for...of:

    var realArray = [];
    for(const element of arrayLike) {
      realArray.append(element);
    }
    
  3. Spread operator:

    [...arrayLike]
    
  4. Object.values:

    var realArray = Object.values(arrayLike);
    
  5. Object.keys:

    var realArray = Object
       .keys(arrayLike)
       .map((key) => arrayLike[key]);
    

Convert Array-like Objects to Arrays in ≤ ES5

Use Array.prototype.slice like so:

var arrayLike = {
  0: 'Value 0',
  1: 'Value 1',
  length: 2
};
var realArray = Array.prototype.slice.call(arrayLike);
realArray = [].slice.call(arrayLike); // Shorter version

realArray.indexOf('Value 1'); // Wow! this works

You can also use Function.prototype.call to call Array.prototype methods on Array-like objects directly, without converting them:

var domList = document.querySelectorAll('#myDropdown option');

domList.forEach(function() { 
  // Do stuff
}); // Error! forEach is not defined.

Array.prototype.forEach.call(domList, function() { 
  // Do stuff
}); // Wow! this works

You can also use [].method.bind( arrayLikeObject ) to borrow array methods and glom them on to your object:

var arrayLike = {
  0: 'Value 0',
  1: 'Value 1',
  length: 2
};

arrayLike.forEach(function() {
  // Do stuff
}); // Error! forEach is not defined.

[].forEach.bind(arrayLike)(function(val){
  // Do stuff with val
}); // Wow! this works

Modifying Items During Conversion