Różnica między textContent a innerText

157

Jaka jest różnica między textContenti innerTextw JavaScript?

Czy mogę użyć textContentw następujący sposób:

var logo$ = document.getElementsByClassName('logo')[0];
logo$.textContent = "Example";
JK
źródło
3
Są takie same, ale niektóre przeglądarki obsługują jedną, a inne drugą.
Pointy
@Pointy jaki jest ten, który obsługują wszystkie przeglądarki?
Yehia Awad
6
Dobry blogu o tym
Tyblitz
4
@Pointy, zapoznaj się z wpisem na blogu, na który wskazałem. Twoje stwierdzenie jest nieprawidłowe, jest różnica.
Tyblitz
3
innerTexti textContentzdecydowanie nie są takie same. Wystąpienie pustych przestrzeni w zawartości węzła spowoduje, że dwie właściwości będą dawały inną zawartość, podobnie jak brelementy i inne elementy potomne renderowane na poziomie bloków.
rano

Odpowiedzi:

211

Żadnej z pozostałych odpowiedzi nie udaje się dostarczyć pełnego wyjaśnienia, stąd ta. Kluczowe różnice między innerTexti textContentsą bardzo dobrze opisane w poście Kelly Norton: innerText a textContent . Poniżej znajduje się podsumowanie:

  1. innerTextbył niestandardowy, podczas gdy textContentzostał ustandaryzowany wcześniej.
  2. innerTextzwraca widoczny tekst zawarty w węźle, a textContentzwraca pełny tekst. Na przykład, następujący kod HTML <span>Hello <span style="display: none;">World</span></span>, innerTextpowróci „Hello”, podczas gdy textContentpowróci „Hello World”. Bardziej szczegółową listę różnic można znaleźć w tabeli pod adresem http://perfectionkills.com/the-poor-misunderstood-innerText/ (dalsze czytanie pod adresem „innerText” działa w przeglądarce IE, ale nie w przeglądarce Firefox ).
  3. W rezultacie innerTextjest znacznie bardziej obciążony wydajnością: wymaga informacji o układzie, aby zwrócić wynik.
  4. innerTextjest definiowany tylko dla HTMLElementobiektów, natomiast textContentjest definiowany dla wszystkich Nodeobiektów.

Obejście problemu textContentw IE8- obejmowałoby funkcję rekurencyjną używającą nodeValuena całym childNodesokreślonym węźle, oto próba wypełnienia 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;
}
Tyblitz
źródło
16
Warto również zauważyć: innerTextzamieni <br>elementy w znaki nowej linii, a textContentpo prostu je zignoruje. Tak więc 2 słowa zawierające tylko <br>element między nimi (bez spacji) zostaną połączone podczas używaniatextContent
skerit
5
Czy jest więc jakaś różnica, kiedy używa się ustawiacza? Like elem.textContent = 'foobar'vselem.innerText = 'foobar'
Franklin Yu
1
Kolejna różnica w zachowaniu między innerTexti textContent: Jeśli zmienisz text-transformelement elementu za pomocą CSS, wpłynie to na wynik „innerText”, ale nie na wynik textContent. Na przykład: innerTextz <div style="text-transform: uppercase;">Hello World</div>będzie „HELLO WORLD”, a textContent„Hello World”.
Kobi
25

textContent jest jedynym dostępnym dla węzłów tekstowych:

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

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

W węzłach elementów innerTextocenia elementy <br>, a textContentznaki sterujące:

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 daje:

1
2
3
4 5 6 7 8

span.textContent daje:

1234
5
6
7
8

Ciągi ze znakami sterującymi (np. Nowe wiersze) nie są dostępne w przypadku textContent, gdy treść została ustawiona za pomocą innerText. W drugą stronę (ustaw znaki sterujące z textContent), wszystkie znaki są zwracane zarówno z, jak innerTexti textContent:

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

Martin Wantke
źródło
20

Oba innerTexti textContentsą znormalizowane od 2016 r. Wszystkie Nodeobiekty (w tym węzły czystego tekstu) mają textContent, ale tylko HTMLElementobiekty mają innerText.

Chociaż textContentdziała z większością przeglądarek, nie działa w IE8 lub starszym. Użyj tego wypełnienia, aby działał tylko w przeglądarce IE8. Ten wypełniacz nie będzie działał z IE7 lub starszymi wersjami.

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);
       }
     }
   );
  })();
}

Object.definePropertyMetoda jest dostępnej w IE9 lub w górę, jednak jest ona dostępna w IE8 dla DOM tylko obiekty.

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

Richarda Hamiltona
źródło
2
Oto jego specyfikacja: w3.org/TR/DOM-Level-3-Core/core.html Również (bardzo stara) tabela obsługi przeglądarek ( webdevout.net/browser-support-dom#dom3core ) sugeruje, że jest obsługiwany dla IE9 +, więc dla IE8 i starszych innerTextjest twoim przyjacielem.
geekonaut
Właściwie lepiej nie obsługiwać ie8 lub używać polyfill. Opublikowałem polyfill w moim poście
Richard Hamilton
1
Jak ten polyfill może działać w IE8, jeśli nie był obsługiwany Object.defineProperty()?
Pointy
2
dlaczego nie zaktualizujesz odpowiedzi? html.spec.whatwg.org/multipage/ ...
caub
3
Oto cytat z MDN dotyczący innerText - „Ta funkcja została pierwotnie wprowadzona przez przeglądarkę Internet Explorer i została formalnie określona w standardzie HTML w 2016 r. Po przyjęciu jej przez wszystkich głównych dostawców przeglądarek”.
czad
15

Dla tych, którzy wygooglowali to pytanie i przybyli tutaj. Czuję, że najbardziej klarowna odpowiedź na to pytanie znajduje się w dokumencie MDN: https://developer.mozilla.org/en-US/docs/Web/API/Node/textContent .

Możesz zapomnieć o wszystkich punktach, które mogą Cię zmylić, ale pamiętaj o dwóch rzeczach:

  1. Kiedy próbujesz zmienić tekst, textContentjest to zwykle właściwość, której szukasz.
  2. Kiedy próbujesz pobrać tekst z jakiegoś elementu, innerTextprzybliża tekst, który uzyskałby użytkownik, gdyby podświetlił zawartość elementu kursorem, a następnie skopiował do schowka. I textContentdaje wszystko, widoczne lub ukryte, w tym elementy <script>i <style>.
Północny
źródło
11

TextContent jest obsługiwany przez większość przeglądarek. Nie jest obsługiwany przez ie8 lub starszą wersję, ale można do tego użyć wypełnienia polyfill

Właściwość textContent ustawia lub zwraca zawartość tekstową określonego węzła i wszystkich jego elementów podrzędnych.

Zobacz http://www.w3schools.com/jsref/prop_node_textcontent.asp

Jeremy Ray Brown
źródło
0

textContent zwraca pełny tekst i nie dba o widoczność, podczas gdy innerText tak.

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

Wyjście tekstu Treść:

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

Dane wyjściowe innerText (zwróć uwagę, że innerText rozpoznaje tagi, takie jak <br>i ignoruje ukryty element):

Text with breaking point.
Milan Chandro
źródło
W IE11 zachowanie innerText jest takie samo jak zachowanie textContent.
Sebastian
0

Oprócz wszystkich różnic, które zostały wymienione w innych odpowiedziach, oto kolejna, którą odkryłem dopiero niedawno:

Chociaż innerTextmówi się, że właściwość jest znormalizowana od 2016 r., Wykazuje różnice między przeglądarkami: Mozilla ignoruje znaki U + 200E i U + 200F („lrm” i „rlm”) w innerText, podczas gdy Chrome nie.

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

Firefox zgłasza 3 i 2, Chrome raporty 3 i 3.

Nie jestem jeszcze pewien, czy jest to błąd (a jeśli tak, w której przeglądarce), czy tylko jedna z tych dziwacznych niezgodności, z którymi musimy żyć.

Panie Lister
źródło
-1

innerHTML wykona nawet tagi HTML, które mogą być niebezpieczne, powodując wszelkiego rodzaju ataki typu client-side injection, takie jak XSS oparty na DOM. Oto fragment kodu:

<!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>

Jeśli używasz .textContent, nie oceni znaczników HTML i nie wydrukuje go jako String.

<!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ódła: https://www.scip.ch/en/?labs.20171214

Ashwath Halemane
źródło