Когда браузер загружает страницу, он «читает» (также говорят: «парсит») HTML и генерирует из него DOM-объекты. Для узлов-элементов большинство стандартных HTML-атрибутов автоматически становятся свойствами DOM-объектов.
Например, для такого тега <body id="page">
у DOM-объекта будет такое свойство body.id="page"
.
Но преобразование атрибута в свойство происходит не один-в-один! В этой главе мы уделим внимание различию этих двух понятий, чтобы посмотреть, как работать с ними, когда они одинаковые и когда разные.
DOM-свойства
Ранее мы уже видели встроенные DOM-свойства. Их много. Но технически нас никто не ограничивает, и если этого мало – мы можем добавить своё собственное свойство.
DOM-узлы – это обычные объекты JavaScript. Мы можем их изменять.
Например, создадим новое свойство для document.body
:
document.body.myData = {
name: 'Caesar',
title: 'Imperator'
};
alert(document.body.myData.title); // Imperator
Мы можем добавить и метод:
document.body.sayTagName = function() {
alert(this.tagName);
};
document.body.sayTagName(); // BODY (значением "this" в этом методе будет document.body)
Также можно изменять встроенные прототипы, такие как Element.prototype
и добавлять новые методы ко всем элементам:
Element.prototype.sayHi = function() {
alert(`Hello, I'm ${this.tagName}`);
};
document.documentElement.sayHi(); // Hello, I'm HTML
document.body.sayHi(); // Hello, I'm BODY
Итак, DOM-свойства и методы ведут себя так же, как и обычные объекты JavaScript:
- Им можно присвоить любое значение.
- Они регистрозависимы (нужно писать
elem.nodeType
, неelem.NoDeTyPe
).
HTML-атрибуты
В HTML у тегов могут быть атрибуты. Когда браузер парсит HTML, чтобы создать DOM-объекты для тегов, он распознаёт стандартные атрибуты и создаёт DOM-свойства для них.
Таким образом, когда у элемента есть id
или другой стандартный атрибут, создаётся соответствующее свойство. Но этого не происходит, если атрибут нестандартный.
Например:
<body id="test" something="non-standard">
<script>
alert(document.body.id); // test
// нестандартный атрибут не преобразуется в свойство
alert(document.body.something); // undefined
</script>
</body>
Учтите, что стандартный атрибут для одного тега может быть нестандартным для другого. Например, атрибут "type"
является стандартным для элемента <input>
, но не является стандартным для <body>
. Стандартные атрибуты описаны в спецификации для соответствующего класса элемента.
Мы можем увидеть это на примере ниже:
<body id="body" type="...">
<input id="input" type="text">
<script>
alert(input.type); // text
alert(body.type); // undefined: DOM-свойство не создалось, потому что оно нестандартное
</script>
</body>
Таким образом, для нестандартных атрибутов не будет соответствующих DOM-свойств. Есть ли способ получить такие атрибуты?
Конечно. Все атрибуты доступны с помощью следующих методов:
elem.hasAttribute(name)
– проверяет наличие атрибута.elem.getAttribute(name)
– получает значение атрибута.elem.setAttribute(name, value)
– устанавливает значение атрибута.elem.removeAttribute(name)
– удаляет атрибут.
Эти методы работают именно с тем, что написано в HTML.
Кроме этого, получить все атрибуты элемента можно с помощью свойства elem.attributes
: коллекция объектов, которая принадлежит ко встроенному классу Attr со свойствами name
и value
.
Вот демонстрация чтения нестандартного свойства:
<body something="non-standard">
<script>
alert(document.body.getAttribute('something')); // non-standard
</script>
</body>
У HTML-атрибутов есть следующие особенности:
- Их имена регистронезависимы (
id
то же самое, что иID
). - Их значения всегда являются строками.
Расширенная демонстрация работы с атрибутами:
<body>
<div id="elem" about="Elephant"></div>
<script>
alert( elem.getAttribute('About') ); // (1) 'Elephant', чтение
elem.setAttribute('Test', 123); // (2), запись
alert( elem.outerHTML ); // (3), посмотрим, есть ли атрибут в HTML (да)
for (let attr of elem.attributes) { // (4) весь список
alert( `${attr.name} = ${attr.value}` );
}
</script>
</body>
Пожалуйста, обратите внимание:
getAttribute('About')
– здесь первая буква заглавная, а в HTML – строчная. Но это не важно: имена атрибутов регистронезависимы.- Мы можем присвоить что угодно атрибуту, но это станет строкой. Поэтому в этой строчке мы получаем значение
"123"
. - Все атрибуты, в том числе те, которые мы установили, видны в
outerHTML
. - Коллекция
attributes
является перебираемой. В ней есть все атрибуты элемента (стандартные и нестандартные) в виде объектов со свойствамиname
иvalue
.