innerHTML や jQuery.html() は HTMLをそのまま取得できるわけではない

element.innerHTML を使うと HTML を取得することができます。Mozilla Developer Network (MDN) には次のように書いてあります。

innerHTML は、与えられた要素に含まれる全てのマークアップ と内容を設定または取得します。

element.innerHTML – MDC Doc Centerより


また、jQuery.html() も、innerHTML と同様、HTML を取得することができます。

Get the HTML contents of the first element in the set of matched elements.

.html() – jQuery APIより

でも、これらのメソッドを使っても、HTML のソースをそのまま取得できるわけではないことをご存知でしたか?私は知らずにハマってしまいました。ということで、以下、調べてみた結果です。

例えば、以下の例では、期待通りの HTML が返ってきます。

しかし、以下の場合はどうでしょうか?

<p><div>foo</div></p>

を期待するかもしれませんが、実際は少し異なる値が返ってきます。
Chrome や Safari などの Webkit 系のブラウザであれば、

<p></p><div>foo</div><p></p>

Firefox の場合は、

<p></p><div>foo</div>

という HTML が取得されます。jQuery.html() の場合も同じ結果が得られます。

なぜこのようなことが起こるのでしょうか?不思議に思い、Quora で質問を投げてみました。すると、すぐにどなたかが答えてくれました。(Quora すげー!)また、Twitter でも同様の質問を投げてみたところ、@hogenishi1122 さんが答えてくれました。(感謝!)

innerHTML や jQuery.html() は HTML のソースをそのまま返すわけではなく、ブラウザが一度 DOMツリーに変換したものを返すとのこと。従って、invalid な HTML コードだと、それぞれのブラウザが解釈したDOMツリーが返ってくるというわけでした。

invalid な HTML を書かなければ、さほど問題にはならないかもしれませんが、必ずしも世の中がすべて valid だとは限りません。記憶の片隅に留めておけば、無用な苦労をすることもないかと思います。

innerHTML や jQuery.html() は HTMLをそのまま取得できるわけではない」への2件のフィードバック

  1. y

    比較ソースがどっちも
    var html = document.getElementById(‘main’).innerHTML;
    document.getElementById(‘result’).innerHTML = html;
    になってる気ガス。

    返信
  2. JimboYoshihide 投稿作成者

    わかりづらいですが、比較ソースは JavaScript ではなく HTML なんです。

    返信

コメントを残す

メールアドレスが公開されることはありません。 * が付いている欄は必須項目です

次のHTML タグと属性が使えます: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>