getElementsByClassName究竟是如何在Chrome中运行的?特别是w.r.t. NodeLists&海外省

时间:2014-08-13 00:35:12

标签: javascript google-chrome getelementsbyclassname

以下所有结果均使用Google Chrome v36&它的控制台。

在调试Wordpress插件时,我发现运行这个小Javascript代码段

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

将记录以下内容(在页面加载完成后展开):

[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

如果我调整了片段以等待DOM完成加载:

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

然后它将记录以下内容(在页面加载完成后展开):

[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

我无法理解的是这里究竟发生了什么 - 特别是,为什么length属性只返回“正确”,可以这么说, DOM加载之后。我找到了this explanation

  

可能是,在调用getElementsByTagName时,不存在任何输入元素,但由于NodeLists是动态的,因此当文档加载时,元素将包含所有28个输入。

但是我正在读它说getElementsByTagName解析NodeList直到它可以解析DOM,并且只能在解析DOM时返回length属性,这对我来说似乎不对,因为它仍然有有限的可数元素。

此外,还有[item:function, namedItem:function]更改为[a.someClass.someOtherClass, a.someclass.someOtherClass]的问题,上述内容无法解释。

因此我的问题是:尽管原型保持不变,但是在{DOM}加载之后getElementsByClassName属性未设置(不存在?)的情况下究竟发生了什么? ?这与/为什么输出从length变为[item:function, namedItem:function]

有何关联?

2 个答案:

答案 0 :(得分:5)

如您所见,getElementsByClassName会返回HTMLCollection - 即查询的实时参考。

在DOM准备就绪后,您正在控制台中扩展 live 引用,但在 DOM之前将其记录在之后发生了什么?准备。因为它是 live 引用,所以通过在DOM准备就绪时进行扩展,当HTMLCollection引用内存中的对象时,它会看到DOM已准备好并从完成的DOM中提取。

但是,如果您在暂停执行Javascript时扩展了引用(这可以通过类似debugger的方式完成),那么这就是您要获得的:

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

因为DOM还没有准备就绪。

这就是为什么第一个记录的引用显示为[item: function, namedItem: function],因为当你记录它时,DOM还没有准备好。 DOM准备就绪后,将其记录为[a.someClass.someOtherClass, a.someClass.someOtherClass]

然而,长度输出只是一个数字,而不是对象引用,并按原样记录,这就是为什么它在DOM准备好之前打印0并且在它之后打印2 - 因为它是完全发生了什么,因为在DOM准备好之前没有DOM元素。

答案 1 :(得分:1)

Nodelist是HTMLcollection的超集。具体来说,Nodelist是制作HTMLcollection的构造函数。

var list = document.getElementsByClassName("classname"); console.log(list) 现在您将看到:

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

因此HTMLcollection只是一个包含元素而不是文本的nodeList。 (Nodelist可以包含文本) 要形成节点列表,您必须使用以下方法: Node.childNodes Element.classList

可能还有一些建立它的递归。