Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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

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

like image 773
Paragon Avatar asked Jun 16 '12 15:06

Paragon


2 Answers

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."

like image 185
Pointy Avatar answered Nov 05 '22 07:11

Pointy


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.

like image 27
Damien_The_Unbeliever Avatar answered Nov 05 '22 07:11

Damien_The_Unbeliever