Разница между textContent и innerText

157

В чем разница между textContentи innerTextв JavaScript?

Могу ли я использовать textContentследующим образом:

var logo$ = document.getElementsByClassName('logo')[0];
logo$.textContent = "Example";
JK
источник
3
Они одинаковые, но некоторые браузеры поддерживают один, а другие - другой.
Заостренный
@Pointy, что поддерживают все браузеры?
Yehia Awad
6
Хороший блог о нем
Tyblitz
4
@Pointy, пожалуйста, обратитесь к сообщению в блоге, на которое я указал. Ваше утверждение неверно, есть разница.
Tyblitz
3
innerTextи textContentрешительно не то же самое. Наличие пробелов в содержимом узла приведет к тому, что два свойства приведут к разному содержимому, а также к появлению brэлементов и других отрисованных потомков уровня блока.
атп

Ответы:

212

Ни один из других ответов не дает полного объяснения, отсюда и этот. Ключевые отличия innerTextи textContentочень хорошо изложены в блоге Келли Нортон: innerText vs. textContent . Ниже вы можете найти резюме:

  1. innerTextбыл нестандартным, хотя textContentбыл стандартизирован ранее.
  2. innerTextвозвращает видимый текст , содержащийся в узле, а textContentвозвращает полный текст. Например, на следующий HTML <span>Hello <span style="display: none;">World</span></span>, innerTextбудет возвращать «Hello», в то время как textContentбудет возвращать «Hello World». Более полный список различий см. В таблице по адресу http://perfectionkills.com/the-poor-misunderstood-innerText/ (дальнейшее чтение в разделе innerText работает в IE, но не в Firefox ).
  3. В результате innerTextэто значительно повышает производительность: для получения результата требуется информация макета.
  4. innerTextопределяется только для HTMLElementобъектов, а textContentопределяется для всех Nodeобъектов.

Обходной путь для textContentIE8 - будет включать рекурсивную функцию, использующую nodeValueвсе childNodesуказанные узлы, вот попытка 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
источник
17
Также стоит отметить: innerTextпревратит <br>элементы в символы новой строки, а textContentпросто проигнорирует их. Таким образом, 2 слова с одним <br>элементом между ними (и без пробелов) будут объединены при использованииtextContent
skerit
5
Тогда есть ли разница, когда используется сеттер? Как elem.textContent = 'foobar'противelem.innerText = 'foobar'
Франклин Ю
1
Другое различие в поведении между innerTextи textContent: Если вы измените text-transformэлемент с помощью CSS, это повлияет на результат 'innerText', но не на результат textContent. Например: innerTextof <div style="text-transform: uppercase;">Hello World</div>будет HELLO WORLD, а textContentHello World.
Коби
25

textContent единственный доступный для текстовых узлов:

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

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

В узлах элементов innerTextоценивает <br> элементы, а также textContentоценивает управляющие символы:

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 дает:

1
2
3
4 5 6 7 8

span.textContent дает:

1234
5
6
7
8

Строки с управляющими символами (например, переводы строки) недоступны textContent, если для содержимого задано значение innerText. Другой способ (символы набора управления с textContent), все персонажи возвращаются как с innerTextи textContent:

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

Мартин Уитке
источник
20

Оба innerText& textContentстандартизированы по состоянию на 2016 год. Все Nodeобъекты (включая узлы чистого текста) имеют textContent, но только HTMLElementобъекты имеют innerText.

Хотя textContentработает с большинством браузеров, он не работает на IE8 или более ранних версиях. Используйте этот polyfill, чтобы он работал только в IE8. Этот polyfill не будет работать с IE7 или ранее.

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.definePropertyметод доступен в IE9 или более поздней версии, однако он доступен в IE8 только для объектов DOM.

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
Вот и спецификация для этого: w3.org/TR/DOM-Level-3-Core/core.html Также (очень старая) таблица поддержки браузера ( webdevout.net/browser-support-dom#dom3core ) предполагает, что он поддерживается для IE9 +, поэтому для IE8 и старше, innerTextваш друг.
geekonaut
На самом деле, лучше не поддерживать ie8 или использовать polyfill. Я разместил полифилл в своем посте
Ричард Гамильтон
1
Как этот полифилл может работать в IE8, когда он не поддерживает Object.defineProperty()?
Заостренный
2
почему бы тебе не обновить свой ответ? html.spec.whatwg.org/multipage/...
caub
3
Вот цитата из MDN о innerText: «Эта функция была первоначально введена Internet Explorer и была официально указана в стандарте HTML в 2016 году после ее принятия всеми основными поставщиками браузеров».
Чад
15

Для тех, кто гуглил этот вопрос и приехал сюда. Я чувствую, что наиболее ясный ответ на этот вопрос находится в документе MDN: https://developer.mozilla.org/en-US/docs/Web/API/Node/textContent .

Вы можете забыть все моменты, которые могут вас смущать, но помните 2 вещи:

  1. Когда вы пытаетесь изменить текст, textContentобычно это свойство, которое вы ищете.
  2. Когда вы пытаетесь получить текст из какого-либо элемента, он innerTextприближается к тексту, который получит пользователь, если он выделит содержимое элемента курсором, а затем скопирует в буфер обмена. И textContentдает вам все, видимое или скрытое, в том числе <script>и <style>элементы.
северный
источник
11

textContent поддерживается большинством браузеров. Он не поддерживается ie8 или более ранней версией, но для этого можно использовать polyfill

Свойство textContent устанавливает или возвращает текстовое содержимое указанного узла и всех его потомков.

См. Http://www.w3schools.com/jsref/prop_node_textcontent.asp

Джереми Рэй Браун
источник
0

textContent возвращает полный текст и не заботится о видимости, в то время как innerText делает.

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

Вывод textContent:

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

Вывод innerText (обратите внимание, как innerText знает о тегах, например <br>, и игнорирует скрытый элемент):

Text with breaking point.
Милан Чандро
источник
В IE11 поведение innerText такое же, как и у textContent.
Себастьян
0

Помимо всех различий, которые были названы в других ответах, вот еще одно, которое я обнаружил только недавно:

Хотя innerTextговорят, что это свойство стандартизировано с 2016 года, оно демонстрирует различия между браузерами: Mozilla игнорирует символы U + 200E и U + 200F («lrm» и «rlm») innerText, а Chrome - нет.

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

Firefox сообщает 3 и 2, Chrome сообщает 3 и 3.

Еще не уверен, является ли это ошибкой (и если да, то в каком браузере) или просто одной из тех странных несовместимостей, с которыми нам приходится мириться.

Мистер листер
источник
-1

innerHTML будет выполнять даже теги HTML, которые могут быть опасными, вызывая любые атаки на стороне клиента, такие как XSS на основе DOM. Вот фрагмент кода:

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

Если вы используете .textContent, он не будет оценивать теги HTML и печатать его как строку.

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

Ссылка: https://www.scip.ch/en/?labs.20171214

Ашват Халеман
источник