2009年03月14日
textContentとinnerHTML
Google検索後のページで検索ワードをハイライト表示するGreasemonkeyスクリプトを作ってたときに引っかかったことのメモ。
element - MDN
- innerHTML
- 要素のマークアップと内容を取得・設定します。
- textContent
- 要素とそのすべての子孫要素のテキスト内容を取得・設定します。
HTMLElementから値を取得するときの両者の主な違いは内容にHTMLマークアップを含むかどうかという点ですが、もう一つ、取得内容にエンコードされた特殊文字が含まれる場合も両者に違いがでてきます。ソース上に書かれた「<b>foo</b>」というテキスト(画面上には「<b>foo</b>」と表示される)を取得するとき、innerHTMLはそのまま「<b>foo</b>」が取得されるのに対して、textContentは画面上に表示される「<b>foo</b>」が取得されてきます。なので、textContentで取得した値をinnerHTMLにそのまま設定するとエスケープされていたはずの特殊文字が元に戻ってしまいます。
<p id="input"><b>foo</b></p> <p id="output"></p> <script type="text/javascript"> var input = document.getElementById("input"); var output = document.getElementById("output"); var innerHTML = input.innerHTML; alert(innerHTML); // 「<b>foo</b>」 var textContent = input.textContent; alert(textContent); // 「<b>foo</b>」 output.innerHTML = textContent; // 太字の「foo」が画面に表示される! // ちなみに、テキストノードのnodeValueから取得する場合もtextContentと同じ挙動になります。 var nodeValue = input.firstChild.nodeValue; alert(nodeValue); // 「<b>foo</b>」 </script>
よくありそうな例としては、「画面のテキストの一部をtextContentやテキストノードのnodeValueから取得して、その内部や前後にタグを文字列で書き込んだあとに最後にinnerHTMLに渡してElementに変換する」という処理をすることがあります。このときに取得するテキストにエンコードされた「<」や「>」が含まれていた場合は、取得時に「<」や「>」に戻ってしまっているので再度エンコードし直してやる必要があります。これを忘れると場合によってはXSS脆弱性にもなりかねないので注意!
