IE8でinnerHTMLすると元あった要素の子要素が削除される

JS側で生成したエレメントが2あったとして。

var d1 = document.createElement('div'); d1.id = 'd_1';
d1.appendChild(document.createTextNode('d1ですよ'));
// <div id='d_1'>d1ですよ</div>
var p1 = '<p>p1ですよ</p>';

一方はエレメント作ってもう一方は横着。これをdocument.bodyに順番に挿入する。p1はappendChildできないのでinnerHTMLで。

document.body.appendChild(d1);
setTimeout(function() {
  document.body.innerHTML = p1;
}, 2000);

一応時間差をつけた。d1ですよが表示された後、p1ですよが出てくる。普通です。ではここから再度d1を挿入。

document.body.appendChild(d1);

setTimeout(function() {
  document.body.innerHTML = p1;
},2000);

setTimeout(function() {
  document.body.appendChild(d1);
},4000);

/*
<p>p1ですよ</p>
<div id='d_1'>d1ですよ</div>
となる
*/

Firefoxでしか確認していないけれどChromeOperaもたぶんこう。じゃあIEはということで、d1ですよは表示されない。

IEはどうなっているかというと、

<p>p1ですよ</p>
<div id=d_1></div>

子要素のテキストノードが消えた。あらら。確かめると、

var d1 = document.createElement('div'); d1.id = 'd_1';
d1.appendChild(document.createTextNode('d1ですよ'));
var p1 = '<p>p1ですよ</p>';

document.body.appendChild(d1);
alert(d1.firstChild); // object
document.body.innerHTML = p1;
alert(d1.firstChild); // null

やっぱり無す。これはテキストノード以外でも消える。JS側で生成した要素に限らず、既存の要素ノードであっても同じことなるだろうな。よーわからん。とりあえず、

var d1 = document.createElement('div'); d1.id = 'd_1';
d1.appendChild(document.createTextNode('d1ですよ'));
var p1 = '<p>p1ですよ</p>';

document.body.appendChild(d1);
document.body.removeChild(d1)
document.body.innerHTML = p1;
document.body.appendChild(d1);

/*
<p>p1ですよ</p>
<div id='d_1'>d1ですよ</div>
*/

removeする。要素ノード同士ならreplaceでも大丈夫かな。この問題はIE9で改善されていた。innerHTMLを軽い気持ちで使っているとときどきよく分からないことが起きるから困る。