document.scripts
returns an HTMLCollection
object holding a list of all scripts in a document. Similarly, document.getElementsByTagName("script")
returns another HTMLCollection
object holding a list of all scripts in the document.
I expected the following statement to be true however it's not.
document.scripts === document.getElementsByTagName("script") // false
What is the reason for both these not being equal?
getElementsByTagName() The getElementsByTagName method of Document interface returns an HTMLCollection of elements with the given tag name. The complete document is searched, including the root node.
The "getElementsByTagName is not a function" error occurs for multiple reasons: calling the getElementsByTagName() method on a value that is not a DOM element. placing the JS script tag above the code that declares the DOM elements. misspelling getElementsByTagName (it's case sensitive).
Syntax: var elements = document. getElementsByTagName(name);
After selecting elements using the querySelectorAll() or getElementsByTagName() , you will get a collection of elements as a NodeList . To iterate over the selected elements, you can use forEach() method (supported by most modern web browsers, not IE) or just use the plain old for-loop.
Well, I wasn't able to find the theoretical reasoning here, but it seems that in some cases those might not be strictly equivalent, and implementations have to bear that in mind. For example, in Chromium the implementations are different, and the real funny fact is that both are cached collections:
// renderer/core/dom/document.cc
HTMLCollection* Document::scripts() {
return EnsureCachedCollection<HTMLCollection>(kDocScripts);
}
// renderer/core/dom/container_node.cc
HTMLCollection* ContainerNode::getElementsByTagName(
const AtomicString& qualified_name) {
DCHECK(!qualified_name.IsNull());
if (GetDocument().IsHTMLDocument()) {
return EnsureCachedCollection<HTMLTagCollection>(kHTMLTagCollectionType,
qualified_name);
}
return EnsureCachedCollection<TagCollection>(kTagCollectionType,
qualified_name);
}
It's not just scripts
: all the document HTMLCollection properties (forms, applets, images etc.) are wrapped into EnsureCachedCollection<HTMLCollection>
.
For tags, however, it's EnsureCachedCollection<HTMLTagCollection>
. While HTMLTagCollection is a child of TagCollection (which in turn is a child of HTMLCollection), those are different caches.
Now the way I expect caches to work, the same requests should give the same result... unless you hit different caches. In this case, same result means not just equality of values, but equivalence of objects.
That's why you get strict equivalence between both subsequent calls to document.getElementsByTagName('script')
and subsequent calls to document.scripts
- but not across those.
UPDATE: Check @Alohci answer, it gives a good example of when the results will actually be different by value for those requests.
Here's an example where they give different results. document.scripts returns the set of HTMLElement scripts, where getElementsByTagName("script") returns the set of all scriot elements regardless of namespace.
(The StackSnippets logic adds two script elements to the document beyond those shown in the example code here.)
console.log('There are ' + document.scripts.length + ' document.scripts elements');
console.log('There are ' + document.getElementsByTagName("script").length + ' document.getElementsByTagName("script") elements');
<script>console.log('foo');</script>
<svg><script>console.log('bar');</script></svg>
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With