最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

javascript - Why does replaceChild() behave oddly when replacing one kind of element with another? - Stack Overflow

programmeradmin1浏览0评论

I am relatively new at javascript, and found an interesting behavior that I can't explain today. I have a custom <hr> (with an image) on a website, which displays oddly in IE7 and below. To overe this, I wanted to use replaceChild() in bination with getElementsByTag(). Initially, I simply tried to loop over the list, so:

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);
}

However, this does not work: it actually only gets half the elements, skipping every other one. Printing i gives half-integer values of the actual number of <hr> elements in the document (e.g. if there are 7 <hr/> elements, it prints 4. By contrast, the following does work:

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 is printed the same number of times as there are hrules in the document (but of course is always 0, since I'm not incrementing it), and the hrules are replaced correctly. I recognize that the while here might as well be while(true)--it's just going until it runs out of <hr> elements, but appears to stop after that (it's not printing any more 0s).

I've tried this with a number of different types of elements, and observed that this only occurs when replacing one kind of element with another. I.e., replacing p with div, span with p, etc. If I replace p with p, div with div, etc. the original example works correctly.

Nothing in the documentation I've found (w3schools, various Google search, here, etc.) suggests an obvious answer.

What is going on here? First, why does the second example I offered work - is replaceChild() iterating over the elements automatically? Second, why is the behavior different for different types of element?

I am relatively new at javascript, and found an interesting behavior that I can't explain today. I have a custom <hr> (with an image) on a website, which displays oddly in IE7 and below. To overe this, I wanted to use replaceChild() in bination with getElementsByTag(). Initially, I simply tried to loop over the list, so:

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);
}

However, this does not work: it actually only gets half the elements, skipping every other one. Printing i gives half-integer values of the actual number of <hr> elements in the document (e.g. if there are 7 <hr/> elements, it prints 4. By contrast, the following does work:

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 is printed the same number of times as there are hrules in the document (but of course is always 0, since I'm not incrementing it), and the hrules are replaced correctly. I recognize that the while here might as well be while(true)--it's just going until it runs out of <hr> elements, but appears to stop after that (it's not printing any more 0s).

I've tried this with a number of different types of elements, and observed that this only occurs when replacing one kind of element with another. I.e., replacing p with div, span with p, etc. If I replace p with p, div with div, etc. the original example works correctly.

Nothing in the documentation I've found (w3schools, various Google search, here, etc.) suggests an obvious answer.

What is going on here? First, why does the second example I offered work - is replaceChild() iterating over the elements automatically? Second, why is the behavior different for different types of element?

Share Improve this question asked Jan 5, 2011 at 16:32 Chris KrychoChris Krycho 3,1551 gold badge26 silver badges35 bronze badges
Add a ment  | 

2 Answers 2

Reset to default 6

document.getElementsByTagName is a live access to all the HR elements in the document - it's updated whenever you change the document. You don't get a snapshot of all the HRs in the document whenever you call it.

So, with the first code, you are both incrementing i and reducing the size of hrules.length each time round the loop. This explains why you only see half the steps you expect.

Here's the solution I ended up using, in case anyone else (like @Pav above) is curious.

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]);
}

Essentially, what happens is you get a list of all the hrules in the document. This list is dynamically updated as you interact with it (see Matthew Wilson's answer). Each time you change the first element of the list to a div, it gets removed from the list, and the list is updated accordingly. The result is that you simply need to act on the first element of the list each time until the length of the list is 0.

That's admittedly a little counterintuitive, but it's how the list works.

与本文相关的文章

发布评论

评论列表(0)

  1. 暂无评论