2011-01-05 76 views
5

我在javascript中比较新,发现了一个我今天无法解释的有趣行为。我在网站上有一个自定义的<hr>(带有图片),在IE7及以下版本中显示出奇怪。为了克服这个问题,我想用replaceChild()结合getElementsByTag()。最初,我只是试图遍历所有的列表,因此:为什么在将另一种元素替换为另一种元素时,replaceChild()会出现奇怪的行为?

var hrules = document.getElementsByTagName('hr'); 
for (var i=0; i < hrules.length; i++) { 

    var newHrule = document.createElement("div"); 
    newHrule.className = 'myHr'; 

    hrules[i].parentNode.replaceChild(newHrule, hrules[i]); 

    document.write(i); 
} 

然而,这不起作用:它实际上只能得到一半的元素,跳过每隔一个。 。打印i给出文档中<hr>元件的实际数的一半的整数值(例如,如果有7个<hr/>元件,它打印相反,以下确实工作:

var hrules = document.getElementsByTagName('hr'); 
var i = 0; 
while (i < hrules.length) { 

    var newHrule = document.createElement("div"); 
    newHrule.className = 'myHr'; 

    hrules[i].parentNode.replaceChild(newHrule, hrules[i]); 

    document.write(i); 
} 

i打印的次数与文档中的hrules相同(但当然总是为0,因为我没有增加它),并且hrules被正确地替换了。我认识到while在这里可能是while(true) - - 直到它耗尽<hr>元素,但在此之后似乎停止(它是n再打印0)。

我已经尝试过使用多种不同类型的元素,并且观察到这种情况只发生在将元素替换为另一个种类时发生。即,用div,spanp等代替p,等等。如果我用p代替p,divdiv等,原来的例子工作正常。

我发现的文档(w3schools,各种谷歌搜索,这里等)都没有提供明显的答案。

这是怎么回事?首先,为什么我提供的第二个示例工作是 - replaceChild()自动迭代元素?其次,为什么不同类型的元素的行为不同?

回答

6

document.getElementsByTagName是对文档中所有HR元素的实时访问 - 只要您更改文档就会更新它。无论何时调用文档,都不会获得文档中所有HR的快照。

因此,使用第一个代码,您既增加了i,又减少了每次循环中hrules.length的大小。这就解释了为什么你只看到你期望的一半步骤。

+0

因此,如果我正确理解你,hrules的长度会随着我调用replaceChild()而动态地改变,因为我通过将列表中的元素更改为不同类型的元素来从列表中移除元素?这有点令人惊讶,虽然不一定直观。这也解释了第二部分,我想。 – 2011-01-05 18:19:41

+0

@Chris,你最终解决了这个问题吗?我有完全相同的问题。 – Pav 2011-05-04 04:03:15

+0

@Pav - 请参阅下面的解决方案,我最终提出: – 2011-05-11 14:48:40

4

下面是我最终使用的解决方案,以防其他人(如上面的@Pav)好奇。

var hrules = document.getElementsByTagName('hr'); 

/* Each repetition will delete an element from the list */ 
while (hrules.length) { 
    var newHrule = document.createElement("div"); 
    newHrule.className = 'ieHr'; 

    /* Each iteration, change the first element in the list to a div 
    * (which will remove it from the list and thereby advance the "head" 
    * position forward. */ 
    hrules[0].parentNode.replaceChild(newHrule, hrules[0]); 
} 

本质上,会发生什么是您得到的文档中的所有hrules列表。这个列表在您与之交互时会动态更新(请参阅Matthew Wilson的answer)。每次将列表的第一个元素更改为div时,都会从列表中删除,并且相应地更新列表。结果是,你只需要每次处理列表的第一个元素,直到列表的长度为0.

这确实有点违反直觉,但它是如何工作的。

+2

感谢您的职位:) – Pav 2011-05-13 04:35:27

相关问题