.getElementsByTagName()
(along with .getElementsByName()
and .getElementsByClassName()
) return "live" node lists. These are collections that will always reflect the current state of the DOM, so even if an element gets added or removed after you've declared your collection variable, you will get the most up to date collection. It works because every time you access your variable that references the "live" collection, the DOM is re-scanned. This is great to give you up-to-date results, but not great for performance. So, if your document doesn't dynamically change very much, you are better off not using these methods and instead use .querySelectorAll()
, which returns a static node list (one who's content is established at the time of the method call and not updated even if DOM changes occur later) or simply .getElementById()
if you are looking for a single element that has an id
or .querySelector()
if you are looking for only the first element that matches a CSS selector.
Now, here's the important part, no matter what method you use to get any kind of node list (live or static), you will always get a list object back, even if that list is empty.
What you are experiencing across browsers is just the difference in how they report the object itself to you. However, if you were to access some specific aspect of the object or any members of the object, all browsers would give you the same results and if you are querying prior to the element(s) being parsed, you will have a node list with 0 items in it. This is why it's a best-practice to place your scripts that need access to DOM elements just before the closing body
tag (</body>
), because by that time, all the HTML has been parsed and you will definitely be able to find all elements.
tag so that all your DOM would have rendered. It's a safeguard against issues like you mentioned. The exception are those scripts where things must init before DOM (e.g. AB tests, GA, etc.)
– bigbitecode Apr 26 '18 at 22:32` and before it I have `
– Scott Marcus Apr 26 '18 at 22:35