Why does JavaScript's getElementsByClassName provide an object that is NOT an array?
Asked Answered
C

2

6

I'm trying to get a list in JavaScript (not using jQuery) of all the elements on the page with a specific class name. I therefore employ the getElementsByClassName() function as follows:

var expand_buttons = document.getElementsByClassName('expand');
console.log(expand_buttons, expand_buttons.length, expand_buttons[0]);

Note that I have three anchor elements on my page with the class 'expand'. This console.log() outputs

[] 0 undefined

Next, for kicks, I threw expand_buttons into its own array as follows:

var newArray = new Array(expand_buttons);
console.log(newArray, newArray.length);

This suddenly outputs

[NodeList[3]] 1

and I can click through the nodelist and see the attributes of the three 'expand' anchor elements on the page. It's also worth noting that I was able to get my code working in a w3schools test page.

It may also be of note that my use of document.getElementsByName actually does output (to the console) an array of elements, but when I ask for its length, it tells me 0. Similarly, if I try to access an array element using array_name[0] as normal, it outputs 'undefined', despite there clearly being an element inside of an array when I print the object to the console.

Does anybody have any idea why this might be? I just want to loop through DOM elements, and I'm avoiding jQuery at the moment because I'm trying to practice coding with vanilla JavaScript.

Thanks,

ParagonRG

Campaign answered 16/6, 2012 at 15:5 Comment(4)
check if that function is not changedCowherb
Are you running your code after the DOM is constructed or before?Rhynd
Be careful with w3schools.Megan
More explanationPolytechnic
M
10

It's not so much a JavaScript thing as it is a web browser thing. That API is supplied by a native object (the document object), and by the DOM spec it returns a NodeList object. You can treat a NodeList like an array, and it's similar, but distinctly different (as you've noticed).

You can always copy a NodeList to a new array:

var nodeArr = Array.prototype.slice.call(theNodeList, 0);

or in modern ES2015 environments:

var nodeArr = Array.from(theNodeList);

JavaScript always exists in some runtime context, and the context can include all sorts of APIs that provide facilities to JavaScript code. A web browser is one of those contexts. The DOM is specified in a way that's not especially partial to JavaScript; it's a language-neutral interface definition.

I guess the short version of this answer would be, "because it just does."

Megan answered 16/6, 2012 at 15:8 Comment(1)
If you can use ES2015/ES6 then Array.from is your friendRoz
R
3

It doesn't return an array because the object it returns is "live", specifically it is a live NodeList:

In most cases, the NodeList is a live collection. This means that changes on the DOM tree are going to be reflected on the collection.

Rhynd answered 16/6, 2012 at 15:11 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.