# Атрибуты и DOM-свойства
При чтении HTML браузер генерирует DOM-модель. При этом большинство стандартных HTML-атрибутов становятся свойствами соответствующих объектов.
Например, если тег выглядит как `
`, то у объекта будет свойство `body.id = "page"`.
Но это преобразование -- не один-в-один. Бывают ситуации, когда атрибут имеет одно значение, а свойство -- другое. Бывает и так, что атрибут есть, а свойства с таким названием не создаётся.
Если коротко -- HTML-атрибуты и DOM-свойства обычно, но не всегда соответствуют друг другу, нужно понимать, что такое свойство и что такое атрибут, чтобы работать с ними правильно.
[cut]
## Свои DOM-свойства
Ранее мы видели некоторые встроенные свойства DOM-узлов. Но, технически, никто нас ими не ограничивает.
**Узел DOM -- это объект, поэтому, как и любой объект в JavaScript, он может содержать пользовательские свойства и методы.**
Например, создадим в `document.body` новое свойство и запишем в него объект:
```js
//+ run
document.body.myData = {
name: 'Петр',
familyName: 'Петрович'
};
alert(document.body.myData.name); // Петр
```
Можно добавить и новую функцию:
```js
//+ run
document.body.sayHi = function() {
alert(this.nodeName);
}
document.body.sayHi(); // BODY, выполнилась с правильным this
```
Нестандартные свойства и методы видны только в JavaScript и никак не влияют на отображение соответствующего тега.
Обратим внимание, пользовательские DOM-свойства:
Могут иметь любое значение.
Названия свойств *чувствительны* к регистру.
Работают за счет того, что DOM-узлы являются объектами JavaScript.
## Атрибуты
Элементам DOM, с другой стороны, соответствуют HTML-теги, у которых есть текстовые атрибуты.
Конечно, здесь речь именно об узлах-элементах, не о текстовых узлах или комментариях.
Доступ к атрибутам осуществляется при помощи стандартных методов:
`elem.hasAttribute(name)` - проверяет наличие атрибута
`elem.getAttribute(name)` - получает значение атрибута
Эти методы возвращают именно то значение, которое находится в HTML.
Также все атрибуты элемента можно получить с помощью свойства `elem.attributes`, которое содержит псевдо-массив объектов типа [Attr](http://www.w3.org/TR/DOM-Level-3-Core/core.html#ID-637646024).
В отличие от свойств, атрибуты:
Всегда являются строками.
Их имя *нечувствительно* к регистру (ведь это HTML)
Видны в `innerHTML` (за исключением старых IE)
Рассмотрим отличия между DOM-свойствами и атрибутами на примере HTML-кода:
```html
```
Пример ниже устанавливает атрибуты и демонстрирует их особенности.
```html
```
При запуске кода выше обратите внимание:
`getAttribute('About')` -- первая буква имени атрибута `About` написана в верхнем регистре, а в HTML -- в нижнем, но это не имеет значения, так как имена нечувствительны к регистру.
Мы можем записать в атрибут любое значение, но оно будет превращено в строку. Объекты также будут автоматически преобразованы.
После добавления атрибута его можно увидеть в `innerHTML` элемента.
Коллекция `attributes` содержит все атрибуты в виде объектов со свойствами `name` и `value`.
## Когда полезен доступ к атрибутам?
Когда браузер читает HTML и создаёт DOM-модель, то он создаёт свойства для всех *стандартных* атрибутов.
Например, свойства тега `'A'` описаны в спецификации DOM: HTMLAnchorElement.
Например, у него есть свойство `"href"`. Кроме того, он имеет `"id"` и другие свойства, общие для всех элементов, которые описаны в спецификации в HTMLElement.
Все стандартные свойства DOM синхронизируются с атрибутами, однако не всегда такая синхронизация происходит 1-в-1, поэтому иногда нам нужно значение именно из HTML, то есть атрибут.
Рассмотрим несколько примеров.
### Ссылка "как есть" из атрибута href
Синхронизация не гарантирует одинакового значения в атрибуте и свойстве.
Для примера, посмотрим, что произойдет с атрибутом `"href"` при изменении свойства:
```html
```
Это происходит потому, что атрибут может быть любым, а свойство `href`, в соответствии со спецификацией W3C, должно быть полной ссылкой.
Стало быть, если мы хотим именно то, что в HTML, то нужно обращаться через атрибут.
[smart header="Есть и другие подобные атрибуты"]
Кстати, есть и другие атрибуты, которые не копируются в точности. Например, DOM-свойство `input.checked` имеет логическое значение `true/false`, а HTML-атрибут `checked` -- любое строковое, важно лишь его наличие.
Работа с `checked` через атрибут и свойство:
```html
```
[/smart]
### Исходное значение value
Изменение некоторых свойств обновляет атрибут. Но это скорее исключение, чем правило.
**Чаще синхронизация -- односторонняя: свойство зависит от атрибута, но не наоборот.**
Например, при изменении свойства `input.value` атрибут `input.getAttribute('value')` не меняется:
```html
```
То есть, изменение DOM-свойства `value` на атрибут не влияет, он остаётся таким же.
А вот изменение атрибута обновляет свойство:
```html
```
Эту особенность можно красиво использовать.
Получается, что атрибут `input.getAttribute('value')` хранит оригинальное (исходное) значение даже после того, как пользователь заполнил поле и свойство изменилось.
Например, можно взять изначальное значение из атрибута и сравнить со свойством, чтобы узнать, изменилось ли значение. А при необходимости и перезаписать свойство атрибутом, отменив изменения.
## Классы в виде строки: className
Атрибуту `"class"` соответствует свойство `className`.
Так как слово `"class"` является зарезервированным словом в Javascript, то при проектировании DOM решили, что соответствующее свойство будет называться `className`.
Например:
```html
```
Кстати, есть и другие атрибуты, которые называются иначе, чем свойство. Например, атрибуту `for` (`