document.scripts 不等于 document.getElementsByTagName("script")
document.scripts is not equal to document.getElementsByTagName("script")
document.scripts
returns 一个 HTMLCollection
对象,其中包含文档中所有脚本的列表。同样,document.getElementsByTagName("script")
returns 另一个 HTMLCollection
对象保存文档中所有脚本的列表。
我原以为以下陈述是正确的,但事实并非如此。
document.scripts === document.getElementsByTagName("script") // false
这两个不相等的原因是什么?
好吧,我在这里找不到理论推理,但似乎在某些情况下,这些推理可能并不严格等效,实现时必须牢记这一点。例如,在 Chromium 中,实现是不同的,真正有趣的是两者都是 cached 集合:
// 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);
}
不只是 scripts
:所有文档 HTMLCollection 属性(表单、小程序、图像等)都包含在 EnsureCachedCollection<HTMLCollection>
.
中
然而,对于标签,它是 EnsureCachedCollection<HTMLTagCollection>
。虽然 HTMLTagCollection 是 TagCollection 的子项(后者又是 HTMLCollection 的子项),但它们是不同的缓存。
现在按照我期望的缓存工作方式,相同的请求应该给出相同的结果...除非您访问不同的缓存。在这种情况下,相同的结果不仅意味着值相等,而且意味着对象等价。
这就是为什么在对 document.getElementsByTagName('script')
的后续调用和对 document.scripts
的后续调用之间严格等效的原因 - 但不是跨这些调用。
更新:检查@Alohci 的回答,它给出了一个很好的例子,说明这些请求的结果实际上何时会有所不同。
这是一个他们给出不同结果的例子。 document.scripts returns HTMLElement 脚本集,其中 getElementsByTagName("script") returns 所有 scriot 元素集,不考虑命名空间。
(StackSnippets 逻辑向文档添加了两个脚本元素,超出了此处示例代码中显示的元素。)
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>
document.scripts
returns 一个 HTMLCollection
对象,其中包含文档中所有脚本的列表。同样,document.getElementsByTagName("script")
returns 另一个 HTMLCollection
对象保存文档中所有脚本的列表。
我原以为以下陈述是正确的,但事实并非如此。
document.scripts === document.getElementsByTagName("script") // false
这两个不相等的原因是什么?
好吧,我在这里找不到理论推理,但似乎在某些情况下,这些推理可能并不严格等效,实现时必须牢记这一点。例如,在 Chromium 中,实现是不同的,真正有趣的是两者都是 cached 集合:
// 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);
}
不只是 scripts
:所有文档 HTMLCollection 属性(表单、小程序、图像等)都包含在 EnsureCachedCollection<HTMLCollection>
.
然而,对于标签,它是 EnsureCachedCollection<HTMLTagCollection>
。虽然 HTMLTagCollection 是 TagCollection 的子项(后者又是 HTMLCollection 的子项),但它们是不同的缓存。
现在按照我期望的缓存工作方式,相同的请求应该给出相同的结果...除非您访问不同的缓存。在这种情况下,相同的结果不仅意味着值相等,而且意味着对象等价。
这就是为什么在对 document.getElementsByTagName('script')
的后续调用和对 document.scripts
的后续调用之间严格等效的原因 - 但不是跨这些调用。
更新:检查@Alohci 的回答,它给出了一个很好的例子,说明这些请求的结果实际上何时会有所不同。
这是一个他们给出不同结果的例子。 document.scripts returns HTMLElement 脚本集,其中 getElementsByTagName("script") returns 所有 scriot 元素集,不考虑命名空间。
(StackSnippets 逻辑向文档添加了两个脚本元素,超出了此处示例代码中显示的元素。)
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>