DOM関数・メソッド

html

【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
  • タグを返す
  • htmlのソースイメージの通りに

    スペースや改行が挿入される。

  • タグが解析され

    DOM要素が構築される。

  • 改行コード・スペースは

    内部的に保持される。

innerText
  • タグを返さない。
  • white-space属性の影響を受け

    表示イメージの通りに
    スペースや改行コード
    が挿入される。

  • タグは解析されず、

    文字列として登録される。

  • 改行コードは、

    <br>要素として登録される。

  • カッコ(<>)と&が

    エンティティ(&lt;、&gt;、&amp;)
    に変換される。

  • スペースは

    内部的に保持される。

textContent
  • タグを返さない。
  • htmlのソースイメージの通りに

    スペースや改行コード
    が挿入される。

  • タグは解析されず、

    文字列として登録される。

  • カッコ(<>)と&が

    エンティティ(&lt;、&gt;、&amp;)
    に変換される。

  • 改行コード・スペースは

    内部的に保持される。

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を再取得します。

テストデモ

<div>\n
スペース____←4個<br>\n
<span_style="color:red">red\n
color</span><br>\n
<span_style="color:blue">青い\n
文字</span><br>\n
&lt;span&nbsp;style=&quot;color:green&quot;&gt;緑\n
文字&lt;/span&gt;\n
</div>\n
スペース ←4個
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の間。
青いと文字の間にスペースが挿入されています。

white-space属性 chrome

innerTextの値にもスペースが挿入されています。

スペース_←4個\nred_color\n青い_文字\n<span_style="color:green">緑_文字</span>

次の図は、Firefox78.0.2でのキャプチャ画像です。
redとcolorの間にスペースが挿入されています。
しかし青いと文字の間にスペースが挿入されていません。

クライアント

innerTextの値にも青い文字の間にスペースが挿入されていません。

スペース_←4個\nred_color\n青い文字\n<span_style="color:green">緑_文字</span>

どうやら日本語文字でのスペースの取り扱い方法が異なるようです。

 

検証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はデータを文字列として取り込みます。
その際、カッコ(<>)と&がエンティティ(&lt;、&gt;、&amp;)に変換されます。

スペースはそのまま取り込まれます。

改行コードは<br>タグに変換され、DOM要素として登録されます。
これによりwhite-space属性に関係なく、画面表示時に改行されます。

textContent の結果

textContentはデータを文字列として取り込みます。
その際、カッコ(<>)と&がエンティティ(&lt;、&gt;、&amp;)に変換されます。

スペース・改行コードはそのまま取り込まれます。
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">&lt;div&gt;<span class="rtcolor">\n</span>
スペース<span class="spcolor">_</span><span class="spcolor">_</span><span class="spcolor">_</span><span class="spcolor">_</span>←4個&lt;br&gt;<span class="rtcolor">\n</span>
&lt;span<span class="spcolor">_</span>style=&quot;color:red&quot;&gt;red<span class="rtcolor">\n</span>
color&lt;/span&gt;&lt;br&gt;<span class="rtcolor">\n</span>
&lt;span<span class="spcolor">_</span>style=&quot;color:blue&quot;&gt;青い<span class="rtcolor">\n</span>
文字&lt;/span&gt;&lt;br&gt;<span class="rtcolor">\n</span>
&amp;lt;span&amp;nbsp;style=&amp;quot;color:green&amp;quot;&amp;gt;緑<span class="rtcolor">\n</span>
文字&amp;lt;/span&amp;gt;<span class="rtcolor">\n</span>
&lt;/div&gt;<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>
&lt;span style=&quot;color:green&quot;&gt;文字&lt;/span&gt;
</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=> ({  '"':"&quot;",
                "&" : "&amp;",
                "<":"&lt;",
                ">":"&gt;",
                "\n":'<span class="rtcolor">\\n</span>' ,
                " " :'<span class="spcolor">_</span>'})[e]
        ).replace( /&lt;br&gt;/g , '<span class="rtcolor">&lt;br&gt;</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&amp;lt;span style=&amp;quot;color:green&amp;quot;&amp;gt;緑の\n文字&amp;lt;/span&amp;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=> ({  '"':"&quot;",
                "&" : "&amp;",
                "<":"&lt;",
                ">":"&gt;",
                "\n":'<span class="rtcolor">\\n</span>' ,
                " " :'<span class="spcolor">_</span>'})[e]
        ).replace( /&lt;br&gt;/g , '<span class="rtcolor">&lt;br&gt;</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

書いた人(管理人):けーちゃん

スポンサーリンク

記事の内容について

null

こんにちはけーちゃんです。
説明するのって難しいですね。

「なんか言ってることおかしくない?」
たぶん、こんなご意見あると思います。

裏付けを取りながら記事を作成していますが、僕の勘違いだったり、そもそも情報源の内容が間違えていたりで、正確でないことが多いと思います。
そんなときは、ご意見もらえたら嬉しいです。

掲載コードについては事前に動作確認をしていますが、貼り付け後に体裁を整えるなどをした結果動作しないものになっていることがあります。
生暖かい視線でスルーするか、ご指摘ください。

ご意見、ご指摘はこちら。
https://note.affi-sapo-sv.com/info.php

 

このサイトは、リンクフリーです。大歓迎です。