【JavaScript】 2023年版innerHTML/innerText/textContentの違い
更新日:2023/01/31
僕は今までDOM要素に文字列をセットするときinnerTextを使っていましたが、最近textContentも同じことができると知りました。
そこで詳しくネットで調べてみるとかなり古い情報が多く、現在の状況とマッチしていないようです。
そこで今回は、innerTextとtextContentおよびinnerHTMLにおいて、今現在(2022/10)はどのような違いがあるのかをお伝えします。
2023/01 タイトルを2022年版から2023年版に変更しました。
検証結果のまとめ
まずは検証した結果からお伝えします。
表の値の取得は、Div要素からinnerHTML/innerText/textContentを使用して取得した値の特徴について解説しています。
値のセットは、タグを含んだ文字列をDiv要素のinnerHTML/innerText/textContentにセットしたときにどうなるかを解説しています。
プロパティ | 値の取得 | 値のセット |
---|---|---|
innerHTML |
|
|
innerText |
|
|
textContent |
|
|
innerTextは少し特殊で、取得時にスタイル属性white-spaceの影響を受けます。
他の二つは影響をうけません。
ちなみにこれらのプロパティは、イコールを使用して値の取得・セットをおこないます。
例:
dom要素.innerHTML = 変数(文字列)
変数 = dom要素.innerHTML
イコールは代入操作ですが、直接プロパティに代入されるわけではなく、内部的に解析処理がおこなわれます。
例えば、innerHTMLは文字列を解析してDOMを構築します。
詳しくは、次のページを見てください。
参考記事:【JavaScript】 ゲッター・セッターとは?必要性はあるのか?
検証1:データを取得する
まずはDOM要素として構築されているデータを取得したとき、各プロパティの違いについて検証してみます。
テストデモ
次のデモは、表示イメージとして用意したDOM要素をinnerHTML・innerText・textContentで取得して内容を表示しています。
ただし表示の際に、スペースを緑の下線(_)で表示しています。
また改行コードを青文字(\n)で表示しています。
改行コードやスペース・HTMLエンティティの取り扱いを確認したいので、htmlコードにそれぞれの要素を含ませています。
white-spaceは、スタイル属性のwhite-spaceを設定します。
white-space属性は、改行やスペースの画面表示方法に関する属性です。
このセレクトボックスを変更すると、innerHTML・innerText・textContentを再取得します。
テストデモ
スペース____←4個<br>\n
<span_style="color:red">red\n
color</span><br>\n
<span_style="color:blue">青い\n
文字</span><br>\n
<span style="color:green">緑\n
文字</span>\n
</div>\n
red
color
青い
文字
<span style="color:green">緑
文字</span>
innerHTMLの取得結果
innerTextの取得結果
textContentの取得結果
ブラウザのユーザーエージェント
innerHTML
上の結果を見ると、innerHTMLはタグを含んだ文字列を返しています。
また改行やスペース・HTMLエンティティは、元のhtmlソースのイメージそのままで取得しています。
white-space属性を変更しても、取得結果は変わりません。
innerText
innerTextはタグが削除されます。
またHTMLエンティティは、対応する文字に変換されます。
innerTextはwhite-space属性の影響を受けます。
表示されているイメージの通りに改行とスペースがセットされます。
textContent
textContentはタグが削除されます。
またHTMLエンティティは、対応する文字に変換されます。
textContentはwhite-space属性の影響を受けません。
改行およびスペースは、元のhtmlソースのイメージそのままで取得しています。
innerText捕捉
white-space属性で改行コードで改行を行わないキーワード(normal等)を指定した場合、改行コードはスペースに変更されます。
しかしブラウザによって、動作が異なることがあります。
次の図は、Google Chrome84.0.4147.89でのキャプチャ画像です。
redとcolorの間。
青いと文字の間にスペースが挿入されています。
innerTextの値にもスペースが挿入されています。
次の図は、Firefox78.0.2でのキャプチャ画像です。
redとcolorの間にスペースが挿入されています。
しかし青いと文字の間にスペースが挿入されていません。
innerTextの値にも青い文字の間にスペースが挿入されていません。
どうやら日本語文字でのスペースの取り扱い方法が異なるようです。
検証2:文字列をセットしたときの動作
次は文字列をDOM要素にセットしたときの違いについて検証してみます。
テストデモ
下のテストデモはテキストボックスに入力した文字列を、innerHTML、innerText、textContentを使用してdiv要素にセットしています。
ただし文字列中の"\n"については、セット前に改行コードに変換しています。
また、div要素はwhite-space属性にnormal(改行をスペースに変換)を指定したものと、pre(改行をそのまま反映)を指定したものの2種類用意してあります。
div要素セット後にdiv要素のinnerHTMLを取得して、表示しています。
これにより、データ文字列をどのようにDOM要素に展開しているか確認できます。
テキストボックスには初期値としてタグとHTMLエンティティ入りの文字列が入力されています。
そのまま反映ボタンを押してみてください
テストデモ
データ文字列
データ文字列を innerHTML にセット
innerHTMLで取得
データ文字列を innerText にセット
innerHTMLで取得
データ文字列を textContent にセット
innerHTMLで取得
ブラウザのユーザーエージェント
innerHTMLの結果
innerHTMLはタグが解析され、DOM要素が構築されます。
また改行・スペース・HTMLエンティティは、そのまま文字列として取り込まれます。
innerTextの結果
innerTextはデータを文字列として取り込みます。
その際、カッコ(<>)と&がエンティティ(<、>、&)に変換されます。
スペースはそのまま取り込まれます。
改行コードは<br>タグに変換され、DOM要素として登録されます。
これによりwhite-space属性に関係なく、画面表示時に改行されます。
textContent の結果
textContentはデータを文字列として取り込みます。
その際、カッコ(<>)と&がエンティティ(<、>、&)に変換されます。
スペース・改行コードはそのまま取り込まれます。
white-space属性が改行コードで改行させないキーワードの場合、改行されません。
参考:ソースコード
参考になる部分はあまりないと思いますが、検証で使用したプログラムのソースコードを紹介します。
CSS
共通スタイル
.tarea,.tarea2{
width:95%;
height:100px;
padding:10px;
background:white;
}
.tarea2{
white-space:pre;
overflow:auto;
}
.tdivarea{
width:95%;
margin:0 0 1em 0;
border: 1px solid black;
padding:2em 10px 10px 10px;
background:white;
position: relative;
overflow: auto;
display: block;
}
.tdivarea.divarea{
white-space: nowrap;
}
.tdivarea:before{
position: absolute;
top: 0;
width: 100%;
background: gray;
left: 0;
color: white;
}
.tbutton{
width:98%;
margin: 5px auto 1em;
}
.flx{
display: flex;
width: 95%;
}
.divarea{ white-space:normal; }
.divarea:before{
content: "【white-space:normal】";
}
.prearea{ white-space:pre; }
.prearea:before{
content: "【white-space:pre】";
}
#htmlarea{white-space:pre;
}
#htmlarea:before{
content: "【HTML】";
}
#htmlviewarea:before{
content: "【表示イメージ】";
}
.rtcolor{color:blue;margin: 0 2px;}
.spcolor{color:green;margin: 0 2px;}
.waku p:first-child{
position: absolute;
top:-1em;
font-weight: bold;
background: white;
padding: 0 1em;
}
.waku{
border: 1px solid black;
padding: 1.5em 10px;
position: relative;
margin:1em 0 2em 0;
}
.ws-normal{white-space:normal;}
.ws-nowrap{white-space:nowrap;}
.ws-pre{white-space:pre;}
.ws-pre-wrap{white-space:pre-wrap}
.ws-pre-line{white-space:pre-line;}
検証1
HTML
<label>white-space:
<select name="ws1" id="whiteSpBox">
<option value="ws-normal" selected>normal</option>
<option value="ws-nowrap">nowrap</option>
<option value="ws-pre">pre</option>
<option value="ws-pre-wrap">pre-wrap</option>
<option value="ws-pre-line">pre-line</option>
</select></label>
<div class="flx">
<div id="htmlarea" class="tdivarea"><div><span class="rtcolor">\n</span>
スペース<span class="spcolor">_</span><span class="spcolor">_</span><span class="spcolor">_</span><span class="spcolor">_</span>←4個<br><span class="rtcolor">\n</span>
<span<span class="spcolor">_</span>style="color:red">red<span class="rtcolor">\n</span>
color</span><br><span class="rtcolor">\n</span>
<span<span class="spcolor">_</span>style="color:blue">青い<span class="rtcolor">\n</span>
文字</span><br><span class="rtcolor">\n</span>
&lt;span&nbsp;style=&quot;color:green&quot;&gt;緑<span class="rtcolor">\n</span>
文字&lt;/span&gt;<span class="rtcolor">\n</span>
</div><span class="rtcolor">\n</span></div>
<div id="htmlviewarea" class="tdivarea">
<div>
スペース ←4個<br>
<span style="color:red">red
color</span><br>
<span style="color:blue">青い
文字</span><br>
<span style="color:green">緑
文字</span>
</div>
</div>
</div>
<div class="waku"><p>innerHTMLの取得結果</p>
<div id="innerHTMLGetArea" class="tarea2"></div>
</div>
<div class="waku"><p>innerTextの取得結果</p>
<div id="innerTextGetArea" class="tarea2"></div>
</div>
<div class="waku"><p>textContentの取得結果</p>
<div id="textContentGetArea" class="tarea2" ></div>
</div>
<p id="black">ブラウザのユーザーエージェント</p>
<p id="yourbrowser1"></p>
JavaScript
window.addEventListener( "DOMContentLoaded" , ()=> {
const replaceHtml = t =>
t.replace(/["<>\n &]/g,
e=> ({ '"':""",
"&" : "&",
"<":"<",
">":">",
"\n":'<span class="rtcolor">\\n</span>' ,
" " :'<span class="spcolor">_</span>'})[e]
).replace( /<br>/g , '<span class="rtcolor"><br></span>');
const setWhiteSpace = (e,selbox) =>{
[ "ws-normal",
"ws-nowrap",
"ws-pre",
"ws-pre-wrap",
"ws-pre-line",
"ws-break-spaces"].forEach( s => e.classList.remove(s));
e.classList.add( selbox.value );
};
document.getElementById("yourbrowser1").innerText = window.navigator.userAgent;
const htmlviewarea = document.getElementById("htmlviewarea");
const whiteSpBox = document.getElementById("whiteSpBox");
const innerHTMLGetArea = document.getElementById("innerHTMLGetArea");
const innerTextGetArea = document.getElementById("innerTextGetArea");
const textContentGetArea = document.getElementById("textContentGetArea");
const setData = ()=>{
innerHTMLGetArea.innerHTML = replaceHtml(htmlviewarea.innerHTML);
innerTextGetArea.innerHTML = replaceHtml(htmlviewarea.innerText);
textContentGetArea.innerHTML = replaceHtml(htmlviewarea.textContent);
};
setWhiteSpace( htmlviewarea , whiteSpBox);
setData();
whiteSpBox.addEventListener( "change" , ()=> {
setWhiteSpace( htmlviewarea , whiteSpBox);
setData();
});
});
検証2
HTML
<p class="black">データ文字列</p>
<textarea id="dataArea" class="tarea">スペース ←4個<br>\n<span style="color:red">red\ncolor</span><br>\n<span style="color:blue">青い\n文字</span><br>\n&lt;span style=&quot;color:green&quot;&gt;緑の\n文字&lt;/span&gt;</textarea>
<button id="setbutton" class="tbutton">反映</button>
<div class="waku"><p>データ文字列を innerHTML にセット</p>
<div class="flx">
<div id="innerHTMLSetDivArea" class="tdivarea divarea"></div>
<div id="innerHTMLSetPreArea" class="tdivarea prearea"></div>
</div>
<p class="black">innerHTMLで取得</p>
<div id="innerHTMLCheckArea" class="tarea2" ></div>
</div>
<div class="waku"><p>データ文字列を innerText にセット</p>
<div class="flx">
<div id="innerTextSetDivArea" class="tdivarea divarea"></div>
<div id="innerTextSetPreArea" class="tdivarea prearea"></div>
</div>
<p class="black">innerHTMLで取得</p>
<div id="innerTextCheckArea" class="tarea2" ></div>
</div>
<div class="waku"><p>データ文字列を textContent にセット</p>
<div class="flx">
<div id="textContentSetDivArea" class="tdivarea divarea"></div>
<div id="textContentSetPreArea" class="tdivarea prearea"></div>
</div>
<p class="black">innerHTMLで取得</p>
<div id="textContentCheckArea" class="tarea2" ></div>
</div>
<p id="black">ブラウザのユーザーエージェント</p>
<p id="yourbrowser2"></p>
JavaScript
window.addEventListener( "DOMContentLoaded" , ()=> {
const replaceHtml = t =>
t.replace(/["<>\n &]/g,
e=> ({ '"':""",
"&" : "&",
"<":"<",
">":">",
"\n":'<span class="rtcolor">\\n</span>' ,
" " :'<span class="spcolor">_</span>'})[e]
).replace( /<br>/g , '<span class="rtcolor"><br></span>');
document.getElementById("yourbrowser2").innerText = window.navigator.userAgent;
document.getElementById("setbutton").addEventListener("click",()=>{
const testData = document.getElementById("dataArea").value.replace(/\\n/g,"\n");
document.getElementById("innerHTMLSetDivArea").innerHTML = testData;
document.getElementById("innerHTMLSetPreArea").innerHTML = testData;
document.getElementById("innerHTMLCheckArea").innerHTML = replaceHtml(document.getElementById("innerHTMLSetDivArea").innerHTML);
document.getElementById("innerTextSetDivArea").innerText = testData;
document.getElementById("innerTextSetPreArea").innerText = testData;
document.getElementById("innerTextCheckArea").innerHTML = replaceHtml(document.getElementById("innerTextSetDivArea").innerHTML);
document.getElementById("textContentSetDivArea").textContent = testData;
document.getElementById("textContentSetPreArea").textContent = testData;
document.getElementById("textContentCheckArea").innerHTML = replaceHtml(document.getElementById("textContentSetDivArea").innerHTML);
});
});
更新日:2023/01/31
関連記事
スポンサーリンク
記事の内容について
こんにちはけーちゃんです。
説明するのって難しいですね。
「なんか言ってることおかしくない?」
たぶん、こんなご意見あると思います。
裏付けを取りながら記事を作成していますが、僕の勘違いだったり、そもそも情報源の内容が間違えていたりで、正確でないことが多いと思います。
そんなときは、ご意見もらえたら嬉しいです。
掲載コードについては事前に動作確認をしていますが、貼り付け後に体裁を整えるなどをした結果動作しないものになっていることがあります。
生暖かい視線でスルーするか、ご指摘ください。
ご意見、ご指摘はこちら。
https://note.affi-sapo-sv.com/info.php
このサイトは、リンクフリーです。大歓迎です。