# Атрибуты и 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, с другой стороны, соответствуют HTML-теги, у которых есть текстовые атрибуты. Конечно, здесь речь именно об узлах-элементах, не о текстовых узлах или комментариях. Доступ к атрибутам осуществляется при помощи стандартных методов: Эти методы возвращают именно то значение, которое находится в HTML. Также все атрибуты элемента можно получить с помощью свойства `elem.attributes`, которое содержит псевдо-массив объектов типа [Attr](http://www.w3.org/TR/DOM-Level-3-Core/core.html#ID-637646024). В отличие от свойств, атрибуты: Рассмотрим отличия между DOM-свойствами и атрибутами на примере HTML-кода: ```html
``` Пример ниже устанавливает атрибуты и демонстрирует их особенности. ```html
``` При запуске кода выше обратите внимание:
  1. `getAttribute('About')` -- первая буква имени атрибута `About` написана в верхнем регистре, а в HTML -- в нижнем, но это не имеет значения, так как имена нечувствительны к регистру.
  2. Мы можем записать в атрибут любое значение, но оно будет превращено в строку. Объекты также будут автоматически преобразованы.
  3. После добавления атрибута его можно увидеть в `innerHTML` элемента.
  4. Коллекция `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` (`