Когда браузер загружает страницу, он «читает» (также говорят: «парсит») 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.