Атрибуты и свойства
Разница между HTML-атрибутами и DOM-свойствами в JavaScript: getAttribute, setAttribute, hasAttribute, removeAttribute, синхронизация value/href, boolean-атрибуты и data-* через dataset.
Чтобы в совершенстве владеть JavaScript, необходимо понимать, как он взаимодействует с объектной моделью документа (DOM). В этом руководстве рассматриваются атрибуты и свойства DOM: как их читать, изменять и синхронизировать для динамического управления веб-страницами.
Введение в DOM в JavaScript
DOM представляет веб-страницу в виде иерархического дерева объектов, позволяя языкам программирования, таким как JavaScript, взаимодействовать с содержимым, стилями и структурой страницы. Каждый элемент HTML-документа отражён в DOM в виде объекта, и у этих объектов есть свойства и атрибуты, которыми можно управлять с помощью JavaScript.
Различия между атрибутами и свойствами
Несмотря на то что термины «атрибуты» и «свойства» нередко используются как синонимы, в контексте DOM они имеют разные значения:
- Атрибуты: определяются в HTML-коде и предоставляют дополнительную информацию об HTML-элементах. Атрибуты всегда являются string-значениями; доступ к ним осуществляется с помощью таких методов, как
getAttribute()иsetAttribute(). - Свойства: характеристики DOM-объектов, представляющих HTML-элементы. Свойства могут быть любого типа данных — boolean, string, число — и доступны напрямую через точечную нотацию.
Если кратко: атрибут — это то, что вы написали в HTML-источнике; свойство — это то, во что браузер разобрал этот атрибут и что представляет на JavaScript-объекте. Для простых случаев вроде id они выглядят одинаково, но это две разные вещи.
Примечание о синхронизации: для большинства стандартных атрибутов (например,
id,class) изменение атрибута обновляет соответствующее свойство и наоборот. Однако такая синхронизация не гарантирована везде, и некоторые важные атрибуты намеренно её нарушают (см. Когда синхронизация нарушается ниже).
Пример кода: доступ к атрибутам и свойствам
<!-- snippet: html-result -->
<div id="demo" class="sample" data-level="1">Hello, World!</div>
<br />
<div>first getAttributes result (data-level): <span id="1"></span></div>
<div>className property: <span id="2"></span></div>
<script>
const demoElement = document.getElementById("demo");
const span1 = document.getElementById("1");
const span2 = document.getElementById("2");
// Accessing an attribute
let classAttribute = demoElement.getAttribute("data-level"); // Output: "1"
span1.innerHTML = classAttribute;
// Accessing a property
// Note: 'class' is a reserved keyword in JS, so the property is named 'className'
const classNameProperty = demoElement.className; // Output: "sample"
span2.innerHTML = classNameProperty;
</script>Методы работы с атрибутами
Каждый элемент предоставляет четыре стандартных метода для работы с атрибутами по имени. Они всегда оперируют string-значениями и напрямую соответствуют HTML-источнику:
| Метод | Что делает |
|---|---|
elem.getAttribute(name) | Возвращает значение атрибута в виде string или null, если атрибут отсутствует |
elem.setAttribute(name, value) | Добавляет атрибут или перезаписывает его значение |
elem.hasAttribute(name) | Возвращает boolean: существует ли атрибут? |
elem.removeAttribute(name) | Удаляет атрибут полностью |
Имена атрибутов нечувствительны к регистру (id и ID — одно и то же), а каждое значение считывается как string, даже если оно выглядит как число.
Установка атрибутов
Используйте метод setAttribute(), чтобы добавить новый атрибут или изменить значение существующего атрибута HTML-элемента.
Пример кода: установка атрибутов
<!-- snippet: html-result -->
<div id="demo" class="sample">Hello, World!</div>
<br />
<div>className property after change: <span id="span1"></span></div>
<script>
const demoElement = document.getElementById("demo");
const span1 = document.getElementById("span1");
// Changing the attribute
demoElement.setAttribute("class", "changed");
// The property updates automatically due to attribute-property synchronization
span1.innerHTML = demoElement.className;
</script>Этот фрагмент кода изменяет атрибут class элемента div на значение «changed».
Удаление атрибутов
Чтобы полностью удалить атрибут из HTML-элемента, используйте метод removeAttribute(). Это полезно, когда нужно лишить элемент определённого поведения или стиля, заданного атрибутом.
Комбинируйте его с hasAttribute() для условного выполнения:
if (demoElement.hasAttribute("disabled")) {
demoElement.removeAttribute("disabled");
}Переназначение свойств
Свойства DOM-элементов можно легко переназначить напрямую с помощью точечной нотации, что обеспечивает более гибкое управление характеристиками элемента.
Пример кода: изменение свойств
<!-- snippet: html-result -->
<div id="demo" class="sample">Hello, World!</div>
<br />
<div>className property after change: <span id="span1"></span></div>
<script>
const demoElement = document.getElementById("demo");
const span1 = document.getElementById("span1");
// Changing the property
// Note: 'class' is a reserved keyword in JS, so the property is named 'className'
demoElement.className = "changed";
span1.innerHTML = demoElement.className;
</script>В этом примере изменяется свойство className элемента div, что демонстрирует, как свойства можно использовать для динамического управления характеристиками элемента.
Когда синхронизация атрибута и свойства нарушается
У удобного взаимного отображения есть исключения, которые необходимо знать — иначе можно потратить часы на отладку.
Свойство value у полей ввода
Атрибут value хранит начальное (исходное) значение из HTML. Свойство value хранит текущее значение, которое вводит пользователь. После того как пользователь редактирует поле, они расходятся: свойство меняется, атрибут — нет.
// <input id="name" value="initial">
const input = document.getElementById("name");
// user types "Alice" into the field...
input.getAttribute("value"); // "initial" — still the HTML default
input.value; // "Alice" — the live, current valueТо же самое применимо к <input type="checkbox">: атрибут checked — это начальное состояние, свойство checked — то, отмечен ли элемент прямо сейчас.
Свойство href у ссылок
Для элемента <a href="/page"> метод getAttribute("href") возвращает именно то, что вы написали ("/page"), тогда как свойство href возвращает полностью разрешённый абсолютный URL ("https://example.com/page").
// <a id="link" href="/page">
const link = document.getElementById("link");
link.getAttribute("href"); // "/page"
link.href; // "https://example.com/page"Практическое правило: используйте методы атрибута, когда вам нужно исходное значение точно в том виде, в каком оно написано; используйте свойство, когда нужно живое разобранное значение от браузера.
Boolean-атрибуты
Некоторые HTML-атрибуты — disabled, checked, required, readonly, selected — являются boolean: само их наличие означает true, независимо от значения. disabled="" и disabled="false" оба отключают элемент.
В JavaScript соответствующее свойство является настоящим boolean-значением, что удобнее для переключения:
button.disabled = true; // adds the attribute, disables the button
button.disabled = false; // removes the attribute, enables itИзбегайте setAttribute("disabled", false) — поскольку атрибут присутствует, элемент остаётся отключённым. Вместо этого устанавливайте свойство.
Пользовательские атрибуты данных
Разработчики могут определять пользовательские атрибуты с префиксом data- — это стандартный, ориентированный на будущее способ прикрепить дополнительную информацию к элементу, не изобретая нестандартных атрибутов. Для чтения и записи они используют свойство dataset вместо getAttribute.
При именовании происходит преобразование из kebab-case в HTML в camelCase в JavaScript: data-author становится dataset.author, а data-order-status — dataset.orderStatus. Можно также записывать значения в dataset, чтобы создавать или обновлять соответствующий data-* атрибут.
Пример кода: пользовательские атрибуты данных
<!-- snippet: html-result -->
<div id="demo" data-author="Jane Doe" data-year="2022">Information Panel</div>
<br />
<div>author: <span id="1"></span></div>
<div>year: <span id="2"></span></div>
<script>
const element = document.getElementById("demo");
const span1 = document.getElementById("1");
const span2 = document.getElementById("2");
span1.innerHTML = element.dataset.author;
span2.innerHTML = element.dataset.year;
</script>Заключение
Понимание атрибутов и свойств DOM позволяет динамически управлять элементами страницы и создавать более богатые интерактивные приложения. Помните ключевое различие: атрибуты — это string-значения из вашего HTML-источника, тогда как свойства — это живые типизированные значения на DOM-объекте; и некоторые атрибуты (value, href, boolean-атрибуты) намеренно их разделяют.
Для углублённого изучения обратитесь к связанным главам:
- Изменение документа — создание, вставка и удаление элементов.
- Свойства узлов: тип, тег и содержимое — чтение и изменение текста и HTML элементов.
- Работа со стилями в DOM — управление CSS через
styleиclassName.