Отличие № 1
textContent
возвращает содержимое узла БЕЗ HTML-разметки и БЕЗ СИМВОЛОВ ПЕРЕНОСА СТРОКИ всех потомков элемента, на котором вызвано обращение к этому свойству!!!
Пример элемента DIV с разметкой

Мы видим, что все строчные элементы имеют свои переносы строк. То есть каждый элемент списка переносится на новую строку.
Теперь обратимся к свойству textContent

Теперь обратимся к свойству innerText

Отличие № 2
Второе по важности отличие в том, что innerText зависит от отрисовки элементов, а textContent нет.
Стоит добавить, что:
- innerText описан в стандарте HTML — https://html.spec.whatwg.org
- textContent описан в стандарте DOM — https://dom.spec.whatwg.org
Выдержка из стандарта HTML
элемент.innerText [= значение]
Возвращает текстовое содержимое элемента «в том виде, в каком оно отображено» (as rendered).
Может быть установлено, чтобы заменить дочерние элементы элемента с заданным значением, но с переносами строк, преобразованными в элементы br.
Выдержка из стандарта DOM
элемент.textContent [= значение]
Возвращает текстовое содержимое потомка узла и представляет собой конкатенацию данных всех потомков узла Text в древовидном порядке.
Видео
Пример с разметкой
Есть простая разметка документа:
<p style="display: none;">Что?</p> <p>Где?</p> <p>Когда?</p>
Первый параграф не отрисовался. То есть мы применили CSS-стиль прямо на элементе, который заблокировал отрисовку элемента.

Обращаемся к innerText
Если сейчас мы обратимся к свойству innerText для родителя неотрисованного элемента
document.getElementsByTagName("div")[0].innerText
то получим
"Где? Когда?"
Неожиданно правда? А куда делось слово «Что?». А innerText его не увидел т. к. оно небыло отрисовано.

Обращаемся к textContent
А теперь давайте обратимся к свойству textContent для того же родителя:
document.getElementsByTagName("div")[0].textContent
то получим
" Что? Где? Когда? "

Проблема слипшихся строк при использовании innerText
При использовании интерфейса DOMParser и его метода parseFromString(str, type) замечена проблема. В созданном объекте документа все значения свойств innerText не содержат символов переноса строк. Это беда, если мы хотим выдернуть из какого-нибудь DIV несколько текстов P. Параграфы теряют свои строчные переносы и из-за этого получается некорректная слипшаяся строка, которая не учитывает символы переноса, как при нормальной работе браузера в режиме рендеринга разметки.
Стандарт DOM Parsing and Serialization судя по последним изменениям прекратил своё существование ещё в 2016 году. Но его интерфейсы ещё поддерживаются в браузерах.
Как лечить заболевание «Приклеенных строк»? Решение есть. Поздравляю вас.
Можно использовать HTML-элемент iframe, который умеет создавать объект документа, на основании обычной строки JavaScript. Но есть нюансы.
Во-первых нужно дожидаться события load, когда iframe прогрузит разметку и создаст новый объект документа
Во-вторых нужно, чтобы этот iframe присутствовал на странице текущего документа (в текущей вкладке). Только после этого документ построится и ресурсы подтянутся и только тогда можно будет получить доступ к вложенному в iframe документу при помощи свойства contentDocumet. И только после этого можно будет у вложенного документа достучаться до свойств innerText, объектов, которые построились из строки.
Информационные ссылки
HTML | Алгоритм сбора отображаемого текста
Стандарт HTML — Раздел «3.2.7 The innerText getter and setter» — https://html.spec.whatwg.org/multipage/dom.html#the-innertext-idl-attribute
Стандарт DOM — Раздел «4.4. Interface Node» — https://dom.spec.whatwg.org/#dom-node-textcontent