素人がプログラミングを勉強していたブログ

プログラミング、セキュリティ、英語、Webなどのブログ since 2008

連絡先: すかいぷ:javascripter_  か javascripter あっと tsukkun.net skypeのほうがいいです

文字列から要素を作りたいときはinnerHTMLではなくcreateContextualFragmentを使う

追記:ベンチマークをコメントを元に修正

文字列から要素を作りたい場合、

var temp = document.createElement('div');
temp.innerHTML = '<span>foo bar fizz buzz!</span>';

とやることが多い。
だが、不要なdiv要素ができて気持ち悪いし、for文でchildNodesをひとつずつ処理する必要があって、不便。
divの中にhead要素を入れることはできないので、innerHTML=''としても、要素は作られない。

RangeのcreateContxtualFragmentを使うと、こういった問題を避けることができる。

例えば、上のコードをcreateContextualFragmentを使って書き直すと、

var range = document.createRange();
range.createContextualFragment('<span>foo bar fizz buzz!</span>');

となる。返ってくるものはdocumentFragmentなので、そのままappendChildすることができる。

また、rangeを作るのは別に重くないので、大抵innerHTMLを使うより軽くなる。

document.body.innerHTML='';
var str = '<a href="http://d.hatena.ne.jp/javascripter/">click!</a><span>bbbb!</span>';
console.time('innerHTML');
for (var i = 0; i < 100; i++) {
  var tmp = document.createElement('div');
  tmp.innerHTML = str;
  var range = document.createRange();
  range.selectNodeContents(tmp);
  document.body.appendChild(range.extractContents());
  range.detach();
}
console.timeEnd('innerHTML');
document.body.innerHTML='';
console.time('createContextualFragment');
for (var i = 0; i < 100; i++) {
  var range = document.createRange();
  document.body.appendChild(range.createContextualFragment(str));
  range.detach();
}
console.timeEnd('createContextualFragment');

innerHTML: 88ms
createContextualFragment: 42ms

1000回にしたら
innerHTML: 435ms
createContextualFragment: 295ms
くらい。