Why does JavaScript not convert array-like objects to arrays?

166 views Asked by At

While learning about DOM manipulation I noticed that Document methods such as getElementByTagName or querySelectorAll return HTMLCollection or NodeList objects which, however much they look like arrays, have to be converted to arrays using Arrays.from() if we want these collections to have the very useful array methods. I am wondering why this is so. Is there any particular reason why JS does not automatically convert these collections to arrays?

Edit: It has been brought to my attention that NodeList has forEach() in all major browsers.

2

There are 2 answers

0
Bergi On BEST ANSWER

The DOM collections have their own types, instead of being Array (or at least array subclass) instances, because they are very different from arrays. They are mere views on the DOM, they are not containers storing the elements themselves. They are immutable (i.e. you cannot .push() on them) or even live views (i.e. they always represent the selection in the current state of the document). Also they can only hold DOM nodes, you cannot put arbitrary values inside them like you can insert into arrays.

Sure, they are array-like in that they have indexed properties and a .length, but that's where the similarity ends. Notice that it is only JavaScript that allows you to access the contents with index properties, according to the pure language-agnostic DOM you would use the .item(index) method. All this is why DOM collections got their own hierarchy and have nothing to do with the Array type that is built into JavaScript.

4
saga On

You want the array-like DOM objects to be implicitly convertible to arrays. Javascript is a very dynamic language and performs many such conversions automatically. And it's one of the reasons this language is so hated in the community. For example: 1 == "1" returns true in Javascript.

So the problem you posed is the age old problem of determining where should we draw the line.

As you yourself pointed out, all you need to do is make a call to Arrays.from to get an actual array.