Différence entre textContent et innerText


157

Quelle est la différence entre textContentet innerTextdans JavaScript?

Puis-je utiliser textContentcomme suit:

var logo$ = document.getElementsByClassName('logo')[0];
logo$.textContent = "Example";

3
Ce sont les mêmes, mais certains navigateurs prennent en charge l'un et d'autres l'autre.
Pointy

@Pointy quel est celui que tous les navigateurs prennent en charge?
Yehia Awad le

6
Un bon article de blog à ce sujet
Tyblitz

4
@Pointy, veuillez vous référer au billet de blog que j'ai signalé. Votre déclaration est incorrecte, il y a une différence.
Tyblitz le

3
innerTextet ne textContentsont décidément pas les mêmes. Les occurrences d'espaces blancs dans le contenu du nœud entraîneront un contenu différent pour les deux propriétés, de même que les occurrences d' bréléments et d'autres descendants rendus au niveau du bloc.
amn le

Réponses:


211

Aucune des autres réponses ne parvient à fournir l'explication complète, d'où celle-ci. Les principales différences entre innerTextet textContentsont très bien décrites dans l'article de blog de Kelly Norton: innerText vs textContent . Ci-dessous vous pouvez trouver un résumé:

  1. innerTextétait non standard, alors qu'il textContentétait standardisé plus tôt.
  2. innerTextrenvoie le texte visible contenu dans un nœud, tandis que textContentrenvoie le texte intégral. Par exemple, sur le HTML suivant <span>Hello <span style="display: none;">World</span></span>, innerTextretournera «Hello», tandis que textContentretournera «Hello World». Pour une liste plus complète des différences, consultez le tableau sur http://perfectionkills.com/the-poor-misunderstood-innerText/ (une lecture plus approfondie sur «innerText» fonctionne dans IE, mais pas dans Firefox ).
  3. En conséquence, il innerTextest beaucoup plus lourd en performances: il nécessite des informations de mise en page pour renvoyer le résultat.
  4. innerTextest défini uniquement pour les HTMLElementobjets, tandis que textContentest défini pour tous les Nodeobjets.

Une solution de contournement pour textContentdans IE8- impliquerait une fonction récursive utilisant nodeValuesur tout childNodesle nœud spécifié, voici un essai à un polyfill:

function textContent(rootNode) {
  if ('textContent' in document.createTextNode(''))
    return rootNode.textContent;

  var childNodes = rootNode.childNodes,
      len = childNodes.length,
      result = '';

  for (var i = 0; i < len; i++) {
    if (childNodes[i].nodeType === 3)
      result += childNodes[i].nodeValue;
    else if (childNodes[i].nodeType === 1) 
      result += textContent(childNodes[i]);
  }

  return result;
}

16
À noter également: innerTexttransformera les <br>éléments en caractères de nouvelle ligne, tout textContenten les ignorant. Donc 2 mots avec seulement un <br>élément entre eux (et sans espaces) seront concaténés lors de l'utilisationtextContent
skerit

5
Alors y a-t-il une différence lorsque le setter est utilisé? Like elem.textContent = 'foobar'vselem.innerText = 'foobar'
Franklin Yu

1
Autre différence de comportement entre innerTextet textContent: Si vous modifiez le text-transformd'un élément par CSS, cela affectera le résultat de 'innerText', mais pas le résultat de textContent. Par exemple: innerTextof <div style="text-transform: uppercase;">Hello World</div>sera "HELLO WORLD", tandis que textContentsera "Hello World".
Kobi

25

textContent est le seul disponible pour les nœuds de texte:

var text = document.createTextNode('text');

console.log(text.innerText);    //  undefined
console.log(text.textContent);  //  text

Dans les nœuds d'élément, innerTextévalue les éléments <br>, tandis que textContentévalue les caractères de contrôle:

var span = document.querySelector('span');
span.innerHTML = "1<br>2<br>3<br>4\n5\n6\n7\n8";
console.log(span.innerText); // breaks in first half
console.log(span.textContent); // breaks in second half
<span></span>

span.innerText donne:

1
2
3
4 5 6 7 8

span.textContent donne:

1234
5
6
7
8

Les chaînes avec des caractères de contrôle (par exemple, les sauts de ligne) ne sont pas disponibles avec textContent, si le contenu a été défini avec innerText. Dans l'autre sens (définir les caractères de contrôle avec textContent), tous les caractères sont renvoyés avec innerTextet textContent:

var div = document.createElement('div');
div.innerText = "x\ny";
console.log(div.textContent);  //  xy


20

Les deux innerText& textContentsont standardisés à partir de 2016. Tous les Nodeobjets (y compris les nœuds de texte pur) ont textContent, mais seuls les HTMLElementobjets l'ont innerText.

Bien qu'il textContentfonctionne avec la plupart des navigateurs, il ne fonctionne pas sur IE8 ou une version antérieure. Utilisez ce polyfill pour qu'il fonctionne uniquement sur IE8. Ce polyfill ne fonctionnera pas avec IE7 ou une version antérieure.

if (Object.defineProperty 
  && Object.getOwnPropertyDescriptor 
  && Object.getOwnPropertyDescriptor(Element.prototype, "textContent") 
  && !Object.getOwnPropertyDescriptor(Element.prototype, "textContent").get) {
  (function() {
    var innerText = Object.getOwnPropertyDescriptor(Element.prototype, "innerText");
    Object.defineProperty(Element.prototype, "textContent",
     {
       get: function() {
         return innerText.get.call(this);
       },
       set: function(s) {
         return innerText.set.call(this, s);
       }
     }
   );
  })();
}

La Object.definePropertyméthode est disponible dans IE9 ou supérieur, mais elle est disponible dans IE8 pour les objets DOM uniquement.

https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/defineProperty

https://developer.mozilla.org/en-US/docs/Web/API/Node/textContent


2
Voici également la spécification pour cela: w3.org/TR/DOM-Level-3-Core/core.html Le (très ancien) tableau de prise en charge des navigateurs ( webdevout.net/browser-support-dom#dom3core ) suggère également que il est pris en charge pour IE9 +, donc pour IE8 et les versions antérieures, innerTextc'est votre ami.
geekonaut

En fait, c'est une meilleure idée de ne pas prendre en charge ie8 ou d'utiliser le polyfill. J'ai posté le polyfill dans mon message
Richard Hamilton

1
Comment ce polyfill peut-il fonctionner dans IE8 alors qu'il ne prend pas en charge Object.defineProperty()?
Pointy le

2
pourquoi ne mettez-vous pas à jour votre réponse? html.spec.whatwg.org/multipage/…
caub

3
Voici une citation de MDN sur innerText - "Cette fonctionnalité a été introduite à l'origine par Internet Explorer et a été formellement spécifiée dans la norme HTML en 2016 après avoir été adoptée par tous les principaux fournisseurs de navigateurs."
le chad

15

Pour ceux qui ont googlé cette question et sont arrivés ici. Je pense que la réponse la plus claire à cette question se trouve dans le document MDN: https://developer.mozilla.org/en-US/docs/Web/API/Node/textContent .

Vous pouvez oublier tous les points qui peuvent vous dérouter, mais rappelez-vous 2 choses:

  1. Lorsque vous essayez de modifier le texte, textContentc'est généralement la propriété que vous recherchez.
  2. Lorsque vous essayez de récupérer du texte à partir d'un élément, correspond innerTextapproximativement au texte que l'utilisateur obtiendrait s'il mettait en surbrillance le contenu de l'élément avec le curseur, puis copié dans le presse-papiers. Et textContentvous donne tout, visible ou caché, y compris <script>et <style>éléments.


0

textContent renvoie le texte intégral et ne se soucie pas de la visibilité, contrairement à innerText.

<p id="source">
    <style>#source { color: red; }</style>
    Text with breaking<br>point.
    <span style="display:none">HIDDEN TEXT</span>
</p>

Sortie du texte Contenu:

#source { color: red; } Text with breakingpoint. HIDDEN TEXT

Sortie de innerText (notez comment innerText est conscient des balises comme <br>, et ignore l'élément caché):

Text with breaking point.

Dans IE11, le comportement de innerText est le même que celui de textContent.
Sebastian

0

Mis à part toutes les différences qui ont été citées dans les autres réponses, en voici une autre que je n'ai découverte que récemment:

Même si la innerTextpropriété est dite normalisée depuis 2016, elle présente des différences entre les navigateurs: Mozilla ignore les caractères U + 200E et U + 200F ("lrm" et "rlm") innerText, contrairement à Chrome.

console.log(document.getElementById('test').textContent.length);
console.log(document.getElementById('test').innerText.length);
<div id="test">[&#x200E;]</div>

Firefox rapporte 3 et 2, Chrome rapporte 3 et 3.

Je ne sais pas encore s'il s'agit d'un bogue (et si oui, dans quel navigateur) ou simplement de l'une de ces incompatibilités bizarres avec lesquelles nous devons vivre.


-1

innerHTML exécutera même les balises HTML qui pourraient être dangereuses en provoquant tout type d'attaque par injection côté client comme XSS basé sur DOM. Voici l'extrait de code:

<!DOCTYPE html>
<html>
    <body>
        <script>
            var source = "Hello " + decodeURIComponent("<h1>Text inside gets executed as h1 tag HTML is evaluated</h1>");  //Source
            var divElement = document.createElement("div");
            divElement.innerHTML = source;  //Sink
            document.body.appendChild(divElement);
        </script>
    </body>
</html>

Si vous utilisez .textContent, il n'évaluera pas les balises HTML et ne l'imprimera pas sous forme de chaîne.

<!DOCTYPE html>
<html>
    <body>
        <script>
            var source = "Hello " + decodeURIComponent("<h1>Text inside will not get executed as HTML</h1>");  //Source
            var divElement = document.createElement("div");
            divElement.textContent = source;  //Sink
            document.body.appendChild(divElement);
        </script>
    </body>
</html>

Référence: https://www.scip.ch/en/?labs.20171214

En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.