質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

ただいまの
回答率

88.83%

createTextNodeとtextContentの違い

解決済

回答 3

投稿

  • 評価
  • クリップ 1
  • VIEW 2,233

salah0615

score 45

入力値をもとにHTML文字列を組み立てる場合には、createElement/createTextNodeメソッドを使用すべきであり、textContentプロパティは使えません。

このような記述が教科書にあったのですが、よく分かりません。というのも、

<form>
            <div>
                <label for="name">サイト名: </label><br>
                <input id="name" name="name" type="text" size="30">
            </div>
            <div>
                <label for="url">URL: </label><br>
                <input id="url" name="url" type="url" size="50">
            </div>
            <div>
                <input id="btn" type="button" value="追加">
            </div>
        </form>
        <div id="list"></div>
document.addEventListener("DOMContentLoaded", function() {
        document.getElementById("btn").addEventListener("click", function() {
                let name = document.getElementById("name");
                let url = document.getElementById("url");

                let anchor = document.createElement("a");
                anchor.href = url.value;
                let text = document.createTextNode(name.value);
                anchor.appendChild(text);
                let list = document.getElementById("list");
                list.appendChild(anchor);
            }, false);
    }, false);

このようなコードを実行させ、例えば、サイト名に<h1>test</h1>と入力すると、追加ボタンの下に<h1>text</h1>という文字列がそのまま出力されます。

しかし、このjavascriptのコードは、

document.addEventListener("DOMContentLoaded", function() {
        document.getElementById("btn").addEventListener("click", function() {
                let name = document.getElementById("name");
                let url = document.getElementById("url");

                let anchor = document.createElement("a");
                anchor.href = url.value;
             //以下、変更箇
                anchor.textContent = name.value;      
                list.appendChild(anchor);                
        }, false);
    }, false);


のようにもかけると思うのですが、どうでしょうか。
このような記述だと何か問題はありますでしょうか。

  • 気になる質問をクリップする

    クリップした質問は、後からいつでもマイページで確認できます。

    またクリップした質問に回答があった際、通知やメールを受け取ることができます。

    クリップを取り消します

  • 良い質問の評価を上げる

    以下のような質問は評価を上げましょう

    • 質問内容が明確
    • 自分も答えを知りたい
    • 質問者以外のユーザにも役立つ

    評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

    質問の評価を上げたことを取り消します

  • 評価を下げられる数の上限に達しました

    評価を下げることができません

    • 1日5回まで評価を下げられます
    • 1日に1ユーザに対して2回まで評価を下げられます

    質問の評価を下げる

    teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。

    • プログラミングに関係のない質問
    • やってほしいことだけを記載した丸投げの質問
    • 問題・課題が含まれていない質問
    • 意図的に内容が抹消された質問
    • 過去に投稿した質問と同じ内容の質問
    • 広告と受け取られるような投稿

    評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。

    質問の評価を下げたことを取り消します

    この機能は開放されていません

    評価を下げる条件を満たしてません

    評価を下げる理由を選択してください

    詳細な説明はこちら

    上記に当てはまらず、質問内容が明確になっていない質問には「情報の追加・修正依頼」機能からコメントをしてください。

    質問の評価を下げる機能の利用条件

    この機能を利用するためには、以下の事項を行う必要があります。

質問への追記・修正、ベストアンサー選択の依頼

  • 退会済みユーザー

    退会済みユーザー

    2019/04/25 03:18

    では <h1>hoge<span>fuga</span>hoge</h1> これを dom を使ってどうやって生成する?

    キャンセル

回答 3

checkベストアンサー

+3

nodeを意識した構造の場合createTextNodeとtextContentでは明らかに挙動が違います

<script>
window.addEventListener('DOMContentLoaded', function(e){
  var hoge=document.querySelector('#hoge');
  hoge.textContent+="xxx";
  hoge.appendChild(document.createTextNode("yyy"));
  var n=hoge.firstChild;
  while(n){
    console.log(n.nodeName+":"+(n.nodeValue||"").replace(/\n/g,"\\n"));
    n=n.nextSibling;
  }
});
</script>
<pre id="hoge">aaa
bbb
ccc</pre>
  • textContentでは文字列を連結したデータが戻るだけ
  • createTextNodeをアペンドした場合別Nodeが挿入されていることがわかります

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2019/04/25 09:30 編集

    だからといってtextContentが問題あるわけではありません
    (あくまでもやっていることや結果が違うというだけ)
    なんならinnerHTMLやinsertAdjacentHTMLでもよいでしょう

    キャンセル

  • 2019/05/03 13:31

    なるほど、ありがとうございます。

    キャンセル

+2

Node#textContent

対象が要素ノードであるなら、要素の子ノード全てを削除してから、テキストノードを挿入します。

<p id="sample">foo<span>bar</span>piyo</p>
<script>
'use strict';
const element = document.getElementById('sample');
element.textContent = 'replaced!';
console.log(element.outerHTML); // <p id="sample">replaced!</p>
</script>

Document#createTextNode

「テキストノード」を生成します。
要素ノードの子ノードがテキストノード単体ではなかった場合の挙動が textContent とは違いますが、それは表面的なもので、ノード単位で扱えるのがメリットです。

<p id="sample"></p>
<script>
'use strict';
const element = document.getElementById('sample');
element.appendChild(document.createTextNode('foo'));
element.appendChild(document.createTextNode('bar'));
element.appendChild(document.createTextNode('piyo'));

console.log(element.outerHTML);          // "<p id="sample">foobarpiyo</p>"
console.log(element.textContent);        // "foobarpiyo"
console.log(element.childNodes[0].data); // "foo"
console.log(element.childNodes[1].data); // "bar"
console.log(element.childNodes[2].data); // "piyo"
</script>

Re: salah0615 さん

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2019/05/03 13:33

    はっきりとした違いがわかりました。ありがとうございます。

    キャンセル

+1

https://developer.mozilla.org/ja/docs/Web/API/Node/textContent

Node.textContent プロパティは、ノードおよびその子孫のテキスト内容を表します。

Nodeを追加したり操作したりする機能ではなく、あるノードの子孫要素まで含めて読み書きする機能です。textContent自体が比較的あとに作られた機能であり、単純なNodeの操作を行うための機能ではなかったはずです。(innerHTMLの親戚)

たとえば<a href="">abc<b>def</b></a> であるとき、a要素のtextContentはabcdefになりますが、textContentを上書きすると内部のb要素が消えるなどの作用が働きます。

とはいえ、TextNodeを作ってそれをappendChildして...というのも面倒なので、textContentは便利に使えばいいと思います。(ちなみにcreateTextNodeなどのほうが若干動作が高速である可能性はあります)

余談:
VueやReactなどが使われることが増えて、そもそもDOMのテキストを直接操作する機会自体が減ってきている印象があります。

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2019/05/03 13:32

    textContentができた経緯まで教えていただきありがとうございます。

    キャンセル

15分調べてもわからないことは、teratailで質問しよう!

  • ただいまの回答率 88.83%
  • 質問をまとめることで、思考を整理して素早く解決
  • テンプレート機能で、簡単に質問をまとめられる

関連した質問

同じタグがついた質問を見る