58

I have been coming across the term "Array-Like Object" a lot in JavaScript. What is it? What's the difference between it and a normal array? What's the difference between an array-like object and a normal object ?

ranieribt
  • 1,280
  • 1
  • 15
  • 33
Kramer786
  • 1,238
  • 1
  • 12
  • 26
  • One is an array, and the other is an object. One has array methods, the other may or may not. – Kevin B Apr 17 '15 at 19:14
  • 3
    Array-like object is an object, which you can iterate using regular `for` loop and number indices. Array-like objects are returned from many native DOM methods like `getElementsByClassName()`. – Teemu Apr 17 '15 at 19:14
  • 1
    I think it's not such a bad question. "Array-like" could also imply that the object exposes an `forEach` method for example (it doesn't mean that). Clarifying which characteristics make an object array-like is good :) – Felix Kling Apr 17 '15 at 19:45

5 Answers5

53

What is it?

An Object which has a length property of a non-negative Integer, and usually some indexed properties. For example

var ao1 = {length: 0},                     // like []
    ao2 = {0: 'foo', 5: 'bar', length: 6}; // like ["foo", undefined × 4, "bar"]

You can convert Array-like Objects to their Array counterparts using Array.prototype.slice

var arr = Array.prototype.slice.call(ao1); // []

Whats the difference between it and a normal array?

It's not constructed by Array or with an Array literal [], and so (usually) won't inherit from Array.prototype. The length property will not usually automatically update either.

ao1 instanceof Array; // false
ao1[0] = 'foo';
ao1.length; // 0, did not update automatically

Whats the difference between an array-like object and a normal object?

There is no difference. Even normal Arrays are Objects in JavaScript

ao1 instanceof Object; // true
[] instanceof Object; // true
Paul S.
  • 64,864
  • 9
  • 122
  • 138
  • `and so (usually) won't inherit from Array.prototype` Care to elaborate on the "usually" part ? Isn't something not an array-like but an array if it inherits from `Array.prototype` ? – doubleOrt Nov 08 '17 at 17:24
  • 1
    @Taurus If you set up the prototype in the ES5- way for some custom object, you will get Array-likes `Array.isArray(Object.create(Array.prototype)); // false`. If you use ES6+ `class A2 extends Array` and `super`, you will get Arrays `Array.isArray(new A2); // true` – Paul S. Nov 08 '17 at 21:24
  • @Paul_S. I see this as more of a gotcha with the `isArray` method since it uses the internal `[[class]]` property behind the scenes, than it being proof that an object with `Array.prototype` is an array-like, rather, an object that has array methods available to it (via inheriting from `Array.prototype`, this also means it has a `length` property) and is numerically indexed is not an array-like, it is an array. – doubleOrt Nov 09 '17 at 18:38
  • So, ES6's extends affect the internal `[[class]]` property ? or is there an entirely different mechanism at play here ? – doubleOrt Nov 09 '17 at 18:38
  • 1
    @Taurus in an ES5- version, even if you did something like `function Foo() {}; Foo.prototype = Object.create(Array.prototype); f = new Foo;` consider how `f[0] = 1; f.length; // => 0`. This means it isn't a true Array as setting an index doesn't have the expected side-effects on length. Doing the same with ES6+ does have side effects on length – Paul S. Nov 09 '17 at 22:45
  • @Paul_S. Ahaaa, so it all has to do with the `length` property automatically updating/not-updaing. – doubleOrt Nov 10 '17 at 07:47
  • @PaulS. say there is an array like object `var objSort = {0: 1, 1: 7, 2: 2}`,why it doesnt get sorted by `Array.prototype.sort.call(objSort); ?` – techie_28 Feb 09 '18 at 10:53
  • 1
    @techie_28 add a _length_ and it will sort, with no _length_ your object is not an _Array-like_ – Paul S. Feb 09 '18 at 22:59
  • @PaulS. Yes that worked.But it sorts only when the starting index is `0`.i.e `var objSort = {1: 10, 2: 30,3: 20,length:3}` doesn't gets sorted like `var objSort = {0: 10, 1: 30, 2: 20}` does ` – techie_28 Feb 12 '18 at 04:48
  • The answer to what's the difference should be this: "Objects do not have to contain a length property, but Array-Like objects do." The final statement makes it unclear, which is why people have downvoted the question, above. – Jeff Fischer Dec 03 '18 at 19:28
  • `You can convert Array-like Objects to their Array counterparts`, the true thing is you can convert every object to an empty array by this way. So how can we create an Array-like object which we can be formatted to an array by `Array.prototype.slice` just like on `arguments`. – CodeAlien Jan 09 '21 at 05:20
6

The famous HTMLCollection (documentation) and the arguments (documentation) are array-like object that automatically created.

Some quick array-like (e.g HTMLCollection) differences between real array examples:

var realArray = ['value1', 'value2'];
var arrayLike = document.forms; 

Similarities:

The length getter is the same:

arrayLike.length; // returns 2;
realArray.length; // returns 2; //there are 2 forms in the DOM.

The indexed getter is the same:

arrayLike[0]; // returns an element.
realArray[0]; // returns an element. ('value')

They are both objects:

typeof arrayLike; // returns "object"
typeof realArray; // returns "object"

Differences:

In array-like the join(), concat(), includes() etc, methods are not a functions:

arrayLike.join(", "); // returns Uncaught TypeError: arrayLike.join is not a function (also relevant to `concat()`, `includes()` etc.)
realArray.join(", "); // returns "value1, value2"

The array like is not really an array:

Array.isArray(arrayLike); //returns "false"
Array.isArray(realArray); //returns "true"

In array like you can't set the length property:

arrayLike.length = 1;
arrayLike.length; //return 2; //there are 2 forms in the DOM.
realArray.length = 1;
realArray.length; //return 1;
Shahar Shokrani
  • 7,598
  • 9
  • 48
  • 91
1

To begin with, an array is a specialised object. Specialised in that:

  • There is a special literal syntax [ … ]
  • There is a length property which is automatically updated
  • The array prototype includes the functions that you normally expect from an array

The other obvious feature is that all elements have a numeric index.

From JavaScript’s point of view any object which has a length property is close enough to be regarded as an array-like object:

var arrayLikeObject = {
    length: 3,
    name: 'thing',
    '1': 'hello'
};
console.log(arrayLikeObject);

The length property doesn’t have to be correct. Even in a normal array, it’s possible to force the length to be other than the number of actual elements. The missing elements all return undefined.

You can convert from an array-like object to a real array using Array.from(). This function will take various values, but the simplest is something like:

var arrayLikeObject = {
    length: 3,
    name: 'thing',
    '1': 'hello'
};
var array = Array.from(arrayLikeObject);
console.log(array);

From here on, the array has all the usual properties and methods. In the above example, the property [1] is copied into the new array, but the element [name] is not, since it doesn’t belong in a real array.

The Array.from() function also accepts a mapping function as a second parameter. This allows you make any changes you need in transit:

var arrayLikeObject = {
    length: 3,
    name: 'thing',
    '1': 'hello'
};
var array = Array.from(arrayLikeObject,
    (element,index) => element?element.toUpperCase():`Item ${index}`
);
console.log(array);
Manngo
  • 14,066
  • 10
  • 88
  • 110
0

There is also a performance difference. In this video Mathias Bynens recommends to use array over array-like-object because V8 is optimized for common arrays.

Diego
  • 449
  • 1
  • 6
  • 16
-1

I think, in ES6, something is Array-like if it is iterable (has a [Symbol.iterator] property).

Tunaki
  • 132,869
  • 46
  • 340
  • 423
Erich Horn
  • 85
  • 6
  • 1
    'Array-like object' is an actual title to a thing that exists. It has defined properties that can be applied concretely to Objects built and used in certain ways. – monsto Dec 08 '17 at 22:24
  • 1
    You think or you know? According to a statement in this post https://dmitripavlutin.com/javascript-array-from-applications/ you could be right -> Moreover, you can use Array.from() with any object or primitive that implements the iterable protocol – GarfieldKlon May 27 '20 at 15:24
  • 2
    No. `{ length: 5}` is an *array-like object* but not an iterable. – AliN11 Jan 17 '22 at 12:51