How exactly does getElementsByClassName work in Chrome ?, specifically wrt NodeLists & DOMs

All of the following results were obtained using Google Chrome v36 and its console.

While debugging my Wordpress plugin, I found that running this little Javascript snippet

console.log(document.getElementsByClassName("switch-tmce"))
console.log(document.getElementsByClassName("switch-tmce").length)

      

will write the following (extended after the page has finished loading):

[item: function, namedItem: function]
    0: a#ninja_forms_field_10-tmce.hide-if-no-js.wp-switch-editor.switch-tmce
    1: a#ninja_forms_field_15-tmce.hide-if-no-js.wp-switch-editor.switch-tmce
    length: 2
    ninja_forms_field_10-tmce: a#ninja_forms_field_10-tmce.hide-if-no-js.wp-switch-editor.switch-tmce
    ninja_forms_field_15-tmce: a#ninja_forms_field_15-tmce.hide-if-no-js.wp-switch-editor.switch-tmce
    __proto__: HTMLCollection
0

      

If I edited the snippet to wait for the DOM to complete, follow these steps:

window.addEventListener("DOMContentLoaded", function() {
    console.log(document.getElementsByClassName("switch-tmce"))
    console.log(document.getElementsByClassName("switch-tmce").length)
}, false);

      

it will write the following (expanded after the page has finished loading):

[a#ninja_forms_field_10-tmce.hide-if-no-js.wp-switch-editor.switch-tmce, a#ninja_forms_field_15-tmce.hide-if-no-js.wp-switch-editor.switch-tmce, ninja_forms_field_10-tmce: a#ninja_forms_field_10-tmce.hide-if-no-js.wp-switch-editor.switch-tmce, ninja_forms_field_15-tmce: a#ninja_forms_field_15-tmce.hide-if-no-js.wp-switch-editor.switch-tmce, item: function, namedItem: function]
    0: a#ninja_forms_field_10-tmce.hide-if-no-js.wp-switch-editor.switch-tmce
    1: a#ninja_forms_field_15-tmce.hide-if-no-js.wp-switch-editor.switch-tmce
    length: 2
    ninja_forms_field_10-tmce: a#ninja_forms_field_10-tmce.hide-if-no-js.wp-switch-editor.switch-tmce
    ninja_forms_field_15-tmce: a#ninja_forms_field_15-tmce.hide-if-no-js.wp-switch-editor.switch-tmce
    __proto__: HTMLCollection
2

      

I'm having trouble figuring out exactly what is going on here, specifically why the property length

returns "correctly", so to speak, after the DOM has loaded. I found this explanation :

Perhaps no input elements exist when calling getElementsByTagName, but since NodeLists are dynamic, when the document is loaded, the elements will contain all 28 inputs.

but I am reading this saying that getElementsByTagName parses the NodeList until it can length

parse the DOM and may return a property when parsing the DOM, which seems wrong to me since it still has finite countable elements.

In addition, there is also the issue of replacing [item:function, namedItem:function]

with [a.someClass.someOtherClass, a.someclass.someOtherClass]

, which is not explained above.

Hence my question is, what exactly is going on under the hood with getElementsByClassName

that property is length

not set (doesn't exist?) Until the DOM is loaded, even though the prototype remains the same? How is this related to / why does the output change from [item:function, namedItem:function]

to [a.someClass.someOtherClass, a.someclass.someOtherClass]

?

+3


source to share


2 answers


As you can see, it getElementsByClassName

returns HTMLCollection

- that is, a live link for your request.

Which is because you are expanding the live link in the console after the DOM is ready, but by running it before the DOM is ready. Since this is a live reference, expanding when the DOM is ready, when it HTMLCollection

references an object in memory, it sees the DOM is ready and pulls from the completed DOM.

If, however, you widen the link by pausing the Javascript execution (this can be done with something like debugger

), this is what you get:

[item: function, namedItem: function]
    length: 0
    __proto__: HTMLCollection
0

      



because the DOM won't be ready yet.

This is why the first registered link appeared like [item: function, namedItem: function]

, because when you registered it the DOM was not ready. When the DOM was ready, it was registered as [a.someClass.someOtherClass, a.someClass.someOtherClass]

.

The length output is just a number, not an object reference, and the logs are as they are, so it prints 0 before the DOM is ready and 2 after it - because that's exactly what happens, since there are no DOM elements before DOM ready.

+4


source


Nodelist is a superset of the HTML collection. In particular, Nodelist is a constructor that makes HTMLcollection.

var list = document.getElementsByClassName("classname"); console.log(list)

Now you will see:

__proto__ : NodeList();
console.log(NodeList) //-> function NodeList()

      



So the HTML assembly is just a nodeList that contains elements, not text. (Nodelist can contain text) to form a nodelist you must use the methods: Node.childNodes Element.classList

and maybe some recursion to create it.

+1


source







All Articles