W3docs

Свойства узлов: тип, тег и содержимое

Изучите иерархию классов DOM, свойства nodeType, nodeName, tagName и четыре свойства содержимого: textContent, innerHTML, outerHTML и nodeValue/data.

Каждый узел в дереве DOM является объектом JavaScript, и этот объект предоставляет свойства, которые сообщают вам какого типа узел, какой тег он представляет и какое содержимое хранит. Научившись уверенно читать эти свойства, вы сможете гораздо реже допускать ошибки при навигации по странице и её редактировании. В этой главе рассматриваются иерархия классов узлов, свойства типа и имени (nodeType, nodeName, tagName), а также четыре свойства содержимого, к которым вы будете обращаться ежедневно (textContent, innerHTML, outerHTML и nodeValue/data), — включая то, когда каждое из них безопасно использовать.

Если вы ещё не знакомы с тем, как DOM организован в виде дерева, сначала прочитайте Понимание узлов DOM.

Иерархия классов узлов

Объекты DOM не все имеют одинаковый набор свойств. Они выстроены в иерархию классов, где каждый класс добавляет возможности к родительскому:

  • Node — базовый класс. Каждый узел (элемент, текст, комментарий, документ) наследует от него. Он предоставляет общие свойства: nodeType, nodeName, nodeValue, parentNode и childNodes.
  • Element — узел, являющийся тегом. Добавляет tagName, innerHTML, атрибуты, children и методы запросов.
  • HTMLElement — базовый класс для каждого конкретного HTML-элемента. Подклассы, такие как HTMLInputElement, HTMLAnchorElement и HTMLTableElement, добавляют свойства, специфичные для тега (например, input.value, a.href).
  • Text и Comment — листовые узлы, хранящие текст. Они наследуют от CharacterData, который добавляет свойство data.

Знание этой иерархии объясняет, почему у <div> есть innerHTML, а у текстового узла — нет: innerHTML относится к Element, а текстовый узел элементом не является. Вы можете узнать класс объекта с помощью Object.prototype.toString или имени конструктора:

const div = document.createElement('div');
console.log(div.constructor.name);          // "HTMLDivElement"
console.log(div instanceof HTMLElement);    // true
console.log(div instanceof Element);        // true
console.log(div instanceof Node);           // true

Типы и имена узлов

Типы узлов (nodeType)

Свойство nodeType — это целое число, идентифицирующее категорию узла. Оно доступно только для чтения и является наиболее надёжным способом ветвить логику при обходе DOM, поскольку текстовые узлы и узлы комментариев легко перепутать с элементами. Наиболее распространённые значения:

  • 1 — узел-элемент (Node.ELEMENT_NODE): HTML- или XML-тег, например <div> или <p>.
  • 2 — узел-атрибут (Node.ATTRIBUTE_NODE): устаревший тип; современный код читает атрибуты через getAttribute()/setAttribute(), а не через обход узлов атрибутов.
  • 3 — текстовый узел (Node.TEXT_NODE): текст между тегами, включая пробелы и переносы строк.
  • 8 — узел-комментарий (Node.COMMENT_NODE): HTML-комментарий <!-- ... -->.
  • 9 — узел-документ (Node.DOCUMENT_NODE): сам объект document, корень дерева.

Используйте именованные константы вместо чисел — они лучше читаются и никогда не изменятся:

const div = document.createElement('div');
div.textContent = 'Hello';

console.log(div.nodeType);                          // 1
console.log(div.nodeType === Node.ELEMENT_NODE);    // true

const textNode = div.firstChild;
console.log(textNode.nodeType === Node.TEXT_NODE);  // true

<!-- snippet: html-result -->

<div id="example">Example node</div>
<script>
    const node = document.getElementById("example");
    node.innerHTML = 'Node type is: ' + node.nodeType;
</script>

Имена узлов: nodeName и tagName

Оба свойства возвращают имя узла, но отличаются областью применения:

  • nodeName существует у каждого узла. Для элемента возвращает имя тега; для текстового узла — "#text"; для комментария — "#comment"; для документа — "#document".
  • tagName существует только у элементов. Для не-элементного узла оно равно undefined.

В HTML-документах оба возвращают имя тега в верхнем регистре ("DIV", а не "div"), независимо от того, как вы написали тег:

const div = document.createElement('div');
console.log(div.nodeName);             // "DIV"
console.log(div.tagName);              // "DIV"

const textNode = document.createTextNode('hi');
console.log(textNode.nodeName);        // "#text"
console.log(textNode.tagName);         // undefined

Практическое правило: используйте tagName, если вы уже знаете, что работаете с элементом; используйте nodeName, если можете иметь дело с узлом любого типа.

<!-- snippet: html-result -->

<div id="example"></div>
<script>
    const element = document.getElementById('example');
    element.innerHTML = 'nodeName: ' + element.nodeName;
</script>

Содержимое узлов

Существуют четыре свойства для чтения и записи того, что находится «внутри» узла. Выбор правильного имеет значение для корректности, производительности и безопасности.

textContent — простой текст, безопасно

textContent получает или устанавливает текст узла и всех его потомков, игнорируя любую разметку. При чтении вы получаете объединённый текст с удалёнными тегами. При записи строка вставляется как обычный текст — все < или > экранируются, поэтому это безопасный вариант для отображения ненадёжных данных:

const div = document.createElement('div');
div.innerHTML = '<b>Hi</b> there';

console.log(div.textContent);          // "Hi there"  (tags stripped)

div.textContent = '<script>alert(1)<\/script>';
console.log(div.textContent);          // "<script>alert(1)</script>"  (inert text, not executed)

<!-- snippet: html-result -->

<div id="example"></div>
<script>
  const element = document.getElementById('example');
  element.textContent = 'Updated text content';
</script>

innerHTML — разметка внутри элемента

innerHTML получает или устанавливает HTML между открывающим и закрывающим тегами элемента. При установке строка разбирается как HTML и дочерние элементы перестраиваются:

const div = document.createElement('div');
div.innerHTML = '<p>Para <span>one</span></p>';

console.log(div.innerHTML);            // "<p>Para <span>one</span></p>"
console.log(div.children.length);      // 1  (the <p>)

Предупреждение о безопасности: никогда не присваивайте ненадёжный ввод в innerHTML. Поскольку браузер разбирает его как HTML, строка вроде <img src=x onerror=alert(1)> становится реальным элементом, выполняющим скрипт — это классическая уязвимость межсайтового скриптинга (XSS). Для пользовательских данных используйте textContent или выполняйте очистку перед вставкой.

outerHTML — элемент вместе с его тегом

outerHTML похож на innerHTML, но включает собственные открывающий и закрывающий теги элемента. Запись в него заменяет сам элемент в DOM, что имеет неожиданное следствие — ваша переменная по-прежнему указывает на старый, теперь отсоединённый узел:

const div = document.createElement('div');
div.id = 'box';
div.innerHTML = 'content';

console.log(div.outerHTML);            // '<div id="box">content</div>'

// Setting outerHTML replaces the node; `div` is now stale.

nodeValue / data — текст внутри текстовых и узлов-комментариев

Для текстовых узлов и узлов-комментариев (у которых нет innerHTML) используйте nodeValue или эквивалентное ему data для чтения и записи их содержимого:

const text = document.createTextNode('original');
console.log(text.nodeValue);           // "original"
console.log(text.data);                // "original"

text.data = 'changed';
console.log(text.nodeValue);           // "changed"

// On an element node, nodeValue is null.
const div = document.createElement('div');
console.log(div.nodeValue);            // null

Что использовать?

СвойствоРаботает сЧитаетПарсит HTML при записи?Безопасно для ненадёжных данных
textContentлюбым узломпростой текст потомковнетда
innerHTMLэлементамивнутреннюю разметкуданет (риск XSS)
outerHTMLэлементамиэлемент с его тегомда (заменяет узел)нет (риск XSS)
nodeValue / dataтекстом, комментариемтекст узланетда

Подробнее о вставке и замене содержимого читайте в Изменение документа.

Заключение

Чтение свойств узлов — основа надёжного DOM-скриптинга. Используйте nodeType (с константами Node.*), чтобы различать категории узлов; tagName/nodeName — для идентификации тегов; и выбирайте свойство содержимого осознанно: textContent для безопасного простого текста, innerHTML/outerHTML — когда намеренно нужно разобрать разметку, и nodeValue/data — для текстовых узлов и узлов-комментариев. По умолчанию используйте textContent для всего, что ввёл пользователь.

Практика

Практика
Что указывает свойство 'nodeType' у узла DOM в JavaScript?
Что указывает свойство 'nodeType' у узла DOM в JavaScript?
Was this page helpful?