HTMLCollection 在访问时似乎丢失了所有其他元素

Har*_*ari 1 javascript arrays

正如您在下面的代码中看到的,我在字符串中有一个 html 片段,然后将其解析为一个文档。但是当我遍历它并获取集合中的项目时,只能访问其他所有项目。还有一些行为,比如丢失集合中的项目也会发生,最终只剩下两个项目。

JSFiddle - https://jsfiddle.net/hari7190/xpvt214o/878427/

var response = "<option value='Bobs Dock'>Bobs Dock</option><option 
value='Johns Dock'>Johns Dock</option><option value='Mikes Dock'>Mikes Dock</option><option value='Jacob Dock'>Jacob Dock</option><option value='Foo Dock'>Foo Dock</option>"

parser = new DOMParser();
doc = parser.parseFromString("<select>" + response + "</select>", "text/html");
var options = doc.getElementsByTagName("option");

for(i=0; i<options.length; i++){
    console.log(i, options.length);
    document.getElementById("list").append(options[i]);
}
Run Code Online (Sandbox Code Playgroud)

迭代结果如下:

index - 1 options.length - 3
index - 2 options.length - 2 
Run Code Online (Sandbox Code Playgroud)

谁能解释为什么这个实现会这样?

请注意:我了解如何实现结果(如此),但我正在寻找解释为什么上述代码的行为方式如此。

Yos*_*ein 5

答案在于append函数。您会看到, append(基于更标准的appendChild)函数添加节点并将其与当前父节点分离

请参阅文档

Node.appendChild() 方法将一个节点添加到指定父节点的子节点列表的末尾。如果给定的子节点是对文档中现有节点的引用,则 appendChild() 将其从当前位置移动到新位置(在将节点附加到其他节点之前,不需要从其父节点中删除节点)。

现在,这些option节点的当前父节点是您的select节点。现在,您的options变量 - 它可能看起来像是一个数组,但实际上是一个HTMLCollection. 再次,从文档中

HTML DOM 中的 HTMLCollection 是活动的;当基础文档更改时,它会自动更新。

所以在你的循环中,每次你添加append一个元素时,附加的元素都会从select节点中删除,HTMLCollectionoptions看到这一点并变得更短,但由于i增加了,你跳过了一个元素。

要亲眼看到这一点,您可以debugger;在 jsfiddle 中添加一行并在浏览器中逐行调试。

  • 击败我 6 秒哈哈 - 我唯一的补充是你可以通过克隆和附加`document.getElementById("list").appendChild(options[i].cloneNode(true))`而不是拉HTMLCollection 之外的节点。 (2认同)