В этой статье познакомимся DOM-свойствами и атрибутами, рассмотрим чем они отличаются и как правильно с ними работать. Разберём какие в JavaScript есть методы для выполнения операций над атрибутами.

Чем отличается атрибут от свойства?

Когда браузер читает HTML документ, он строит на его основании DOM. Во время этого процесса HTML атрибуты элементов переводятся в соответствующие им DOM свойства.

Например, браузер, при чтении следующей HTML строчки кода, создаст для этого элемента в DOM свойства id, className, src и alt.

<img id="brand" class="brand" src="logo.png" alt="логотип сайта">

Обращение к этим свойствам в коде JavaScript выполняется как к свойствам объекта. Объектом здесь выступает узел (элемент) в DOM.

Пример, в котором получим значения DOM свойств для элемента, приведённого выше, и выведем их значения в консоль:

var brandImg = document.querySelector('#brand'); // получим элемент

// выведем в консоль DOM-свойства элемента
console.log(brandImg.id); // "brand"
console.log(brandImg.className); // "brand"
console.log(brandImg.src); // "logo.png"
console.log(brandImg.alt); // "логотип сайта"

Некоторые названия DOM-свойств не соответствуют именам атрибутов. Одним из таких является атрибут class. Данному атрибуту соответствует DOM свойство className. Данное отличие связано с тем, что class является ключевым словом в JavaScript, оно зарезервировано и не может использоваться. Из-за этого разработчики стандарта решили использовать для соответствия какое-то другое название, в качестве которого было выбрано className.

Ещё один нюанс связан с тем, что перевод HTML атрибутов в DOM свойства не всегда осуществляется один к одному.

Если элемент имеет нестандартный HTML атрибут, то DOM-свойство, соответствующее ему в большинстве случаев, не создаётся.

<div id="mydiv" alt="..."></div>

<script>
// получим элемент
mydiv = document.querySelector('#mydiv'); 
// получим значение свойство alt элемента и выведем его в консоль
console.log(mydiv.alt); // undefined 
// получим значение атрибут alt элемента и выведем его в консоль
console.log(mydiv.getAttribute('alt')); // "..."
</script>

Другое отличие связано с тем, что значения у определённых HTML атрибутов и соответствующих им DOM-свойств могут быть различными. Т.е. HTML атрибут может иметь одно значение, а DOM свойство, созданное на его основе – другое.

Один из таких атрибутов является checked.

<input type="checkbox" checked>

Значение HTML атрибута checked в данном случае – это пустая строка. Но, DOM-свойство, соответствующее данному атрибуту будет иметь значение true. Т.к. по правилам стандарта для установления true достаточно лишь упоминание этого атрибута в HTML коде и при этом не важно какое он будет иметь значение.

При этом даже если мы в HTML коде не укажем атрибут checked для элемента input с типом checkbox, то для него в DOM всё равно будет создано свойство checked, но оно будет равно false.

<input type="checkbox">

Кроме этого, при изменении DOM изменяется и HTML код документа, и наоборот. Но эта синхронизация касаемо HTML атрибутов и DOM свойств работает достаточно редко, поэтому на неё лучше не полагаться.

Поэтому, когда мы работаем в JavaScript, то лучше опираться именно на свойства, а не атрибуты. Выполнять операции с атрибутами стоит в основном тогда, когда мы хотим получить именно то, что находиться в HTML. Тоже касается и других операций с атрибутами (изменение, добавление и удаление).

В итоге, свойство элемента – это то, что находится в DOM, а атрибут – это то, что находится в HTML.

Другие различия:

  • значение атрибута – это всегда строка, а значение DOM-свойства – определённый тип данных (не обязательно строка);
  • имя атрибута – регистронезависимо, а DOM -свойства - регистрозависимо. Например, атрибут id мы можем в HTML написать, как Id, ID и т.д. Но к соответствующему DOM-свойству мы можем обратиться только по id и никак по-другому.

Работа с DOM свойствами элемента

Работа со свойствами элементов в JavaScript как уже было отмечено выше осуществляется как со свойствами объектов.

Но для того, чтобы обратиться к свойству некоторого элемента, его необходимо сначала получить. Получить DOM элемент в JavaScript можно, например, с помощью универсального метода querySelector, а коллекцию DOM элементов, например, посредством querySelectorAll.

В качестве первого примера рассмотрим следующий HTML элемент:

<div id="alert" class="alert alert-info" title="Текст подсказки...">
  Текст информационного сообщения...
</div>

<script>
  var alert = document.querySelector('#alert'); // получим элемент
</script>

На базе него разберём как осуществляется получение DOM-свойств, их изменение и добавление новых.

Чтение значений DOM-свойств:

// получим значение DOM свойства id
var alertId = alert.id; // "alert"
// получим значение DOM свойства className
var alertClass = alert.className; // "alert alert-info" 
// получим значение DOM свойства title
var alertId = alert.title; // "Текст подсказки..."

Изменение значений DOM-свойств:

// для изменения значения DOM свойству, ему нужно просто присвоить новое значение
alert.title = "Новый текст подсказки"; // присвоим DOM свойству title элемента новое значение
// или так (т.к. обращение к этому свойству мы уже сохранили в переменную alertId)
alertId = "Новый текст подсказки";
// или так (т.к. обращение к этому свойству мы уже сохранили в переменную alertId)
alert.className = "alert alert-warning";

Добавление DOM свойств:

alert.lang = "ru"; // установим свойству lang значение равное "ru"
alert.dir = "ltr"; // установим свойство dir значение равное "ltr"

Пример, в котором выведем в консоль все значения классов, которые есть у элементов p на странице:

var paragraphs = document.querySelectorAll("p");
for (var i = 0, length = paragraphs.length ; i < length; i++) { 
  if (paragraphs[i].className) {
    console.log(paragraphs[i].className);
}

Пример, в котором установим всем элементам с классом content свойство lang со значением "ru":

var contents = document.querySelectorAll('.content');
for (var i = 0, length = contents.length; i < length; i++) {
  contents[i].lang = "ru";
}

Атрибуты элементов и методы для работы с ними

Атрибуты элементов находятся в HTML, а не в DOM. Они в какой-то степени связаны со свойствами, но это не одно и тоже. Когда доступно свойство, то рекомендуется работать именно с ним, а не с атрибутом.

Значения атрибутов как уже было отмечено выше всегда являются строками в отличии от DOM свойств.

В JavaScript для выполнения операций, связанных с атрибутами, имеется четыре метода:

  • .hasAttribute('имя_атрибута') – проверяет наличие указанного атрибута у элемента. Если проверяемый атрибут есть у элемента, то данный метод возвращает true, в противном случае - false.
  • .getAttribute('имя_атрибута') – получает значение атрибута. Если указанного атрибута нет у элемента, то данный метод возвращает пустую строку ("") или null.
  • .setAttribute('имя_атрибута', 'значение_атрибута') – устанавливает указанный атрибут с указанным значением элементу. Если указанный атрибут есть у элемента, то данный метод тогда просто изменит ему значение.
  • .removeAttribute('имя_атрибута') - удаляет указанный атрибут у элемента.

Рассмотрим примеры.

Очень интересный пример с атрибутом value.

Пример с атрибутом value

<input name="name" type="text" value="Bob">

<script>
  var name = document.querySelector('input[name="name"]'); // получим элемент
</script>

Получим значение HTML атрибута value и DOM-свойства value:

// получим значение атрибута value элемента из HTML
name.getAttribute('value'); // "Bob"
// получим значение DOM-свойства value
name.value; // "Bob"

// обновим значение атрибута value, установим ему новое значение
name.setAttribute('value', 'Tom'); // "Tom"
// получим значение DOM свойства value
name.value; // "Tom"

Из этого примера видно, что, изменяя атрибут value, браузер автоматически изменяет в соответствии с ним DOM-свойство value.

Теперь давайте проделаем, наоборот, изменим значение свойства и проверим изменится ли значение атрибута:

// установим новое значение DOM свойству value
name.value = "John";
// получим значение атрибута value элемента из HTML
name.getAttribute('value'); // "Tom"

Из этого примера видно, что синхронизация HTML атрибута и DOM свойства происходит в одностороннем порядке. Т.е. изменение DOM свойства value не изменяет связанный с ним атрибут.

Тоже самое произойдёт, когда пользователь будет вводить текст в это поле. В DOM-свойстве value будет находится действительное значение, а в связанном с ним HTML-атрибуте изначальное или то, которое мы установили, например, с помощью метода setAttribute.

Поэтому более корректно работать всегда со свойствами, а обращаться в HTML только когда это действительно нужно.

Даже и в этом случае, получить значение value, которое находится в HTML, можно с помощью свойства. Это свойство называется defaultValue.

name.defaultValue; // Tom

Ещё один очень интересный пример, но теперь с атрибутом href.

Пример с атрибутом href

Пример, в котором нам нужно получить значение ссылки так, как оно было установлено в HTML.

<a id="link" href="page2.html"></a>

<script>
var page2 = document.querySelector('#page-2");
page2.getAttribute("href"); // page2.html
page2.href; // полный URL, например: http://localhost/page2.html
</script>

В этом примере атрибут href и DOM-свойство href содержат разные значения. В атрибуте href - то, что мы установили, а в DOM-свойстве - полный URL. Это различие продиктовано стандартом, в соответствии с которым браузер должен привести значение DOM-свойства href к полному URL.

Поэтому если нам нужно получить то, что находится в HTML-атрибуте, то без метода getAttribute в этом случае не обойтись.

В завершении разберём ещё атрибут selected.

Пример с атрибутом selected

Пример, в котором показано как можно получить значение выбранной опции select:

<select id="mark">
  <option value="none" selected>нет оценки</option>
  <option value="1">1</option>
  <option value="2">2</option>
  <option value="3">3</option>
  <option value="4">4</option>
  <option value="5">5</option>
</select>

<script>
// получаем элемент select
var mark = document.querySelector('#mark');
// 1 способ
mark.querySelector('option:checked').value;
// 2 способ
mark.value;
</script>

Пример, в котором показано как можно получить выбранные значения опций в элементе select:

<select id="mark" multiple>
  <option value="none" selected>нет оценки</option>
  <option value="1">1</option>
  <option value="2">2</option>
  <option value="3">3</option>
  <option value="4">4</option>
  <option value="5">5</option>
</select>

<script>
// получаем элемент select
var mark = document.querySelector('#mark');
// 1 способ (через создание массива и наполнением его значений выбранных опций)
var arr = [];
for (var i = 0, length = mark.options.length; i < length; i++) {
  if (mark.options[i].selected) {
    arr.push(mark.options[i].value);
  }
}
// 2 способ (более современный, с использованием DOM-свойства selectedOptions)
var arr = Array.from(mark.selectedOptions, option => option.value)
</script>

Ещё один способ работы с HTML атрибутами (свойство attributes)

В JavaScript у каждого элемента имеется свойство attributes, с помощью которого можно получить все его HTML атрибуты в виде объекта NamedNodeMap.

Данный способ может находить применение, когда вам нужно, например перебрать все атрибуты у элемента.

Доступ к атрибуту в этой коллекции осуществляется по его индексу или с помощью метода item. Отсчёт атрибутов в этой коллекции ведётся с 0.

Например, выведем в консоль все атрибуты некоторого элемента:

<p id="message" class="text" style="text-align: center;">I LOVE JAVASCRIPT</p>

<script>
// получим элемент по его идентификатору message
var message = document.querySelector('#message');
// получим его атрибуты
var attrs = message.attributes;
// переберём все атрибуты с помощью цикла (attrs.length – количество атрибутов)
for (var i = 0, length = attrs.length; i < length; i++) {
  // attrs[i] или attrs.item(i)  – обращение к атрибуту в коллекции по его порядковому номеру
  // attrs[i].name – имя атрибута
  // attrs[i].value – значение атрибута (с помощью него можно также изменить значение атрибута)
  console.log(attrs[i].name + ' = ' + attrs[i].value);
  // или с помощью метода item
  console.log(attrs.item(i).name + ' = ' + attrs.item(i).value);
  // пример как можно изменить значение через свойство value
  // if (attrs[i].name === "class") {
  //   attr[i].value = "info";
  // }
}

// в результате выполнения:
// id = message
// class = text
// style = text-align: center;

</script>

Кроме этого, работать с этой коллекцией можно также посредством следующих методов:

  • .getNamedItem('имя_aтpибyтa') – получает значение указанного атрибута (если указанный атрибут отсутствует у элемента, то в качестве результата получим null).
  • .setNamedItem('aтpибyт_yзeл') – добавляет новый атрибут к элементу или обновляет значение у существующего. Для создания атрибута (узла) необходимо использовать метод document.createAttribute(), которому в качестве параметра необходимо передать имя атрибута (узла). После этого созданному атрибуту (узлу) необходимо присвоить значение с помощью свойства value.
  • .removeNamedItem('имя_атрибута') – удаляет указанный атрибут у элемента (в качестве результата возвращает удалённый атрибут).

Пример, работы с атрибутами через методы getNamedItem, setNamedItem и removeNamedItem:

<p id="message" class="text" style="text-align: center;">I LOVE JAVASCRIPT</p>

<script>
  // получим элемент по его идентификатору message
  var message = document.querySelector('#message');
  // получим его аттрибуты
  var attrs = message.attributes;
  // Задача №1. Получим значение атрибута id
  console.log(attrs.getNamedItem('id'));
  // Задача №2. Установим атрибут (если он есть, то изменим его значение, в противном случае добавим новый) 
  // создаём атрибут style и сохраняем его в переменную attrStyle  
  var attrStyle = document.createAttribute('style');
  // присваиваем значение атрибуту с помощью свойства value 
  attrStyle.value = 'text-align: left;';
  // устанавливаем атрибут элементу 
  attrs.setNamedItem(attrStyle);    
  // Задача №3. удалить атрибут class у элемента
  attrs.removeNamedItem("class");     
</script>

Задачи

  1. Вывести в консоль все элементы HTML документа, которые имеют атрибут id.
  2. Добавить атрибут title ко всем изображениям на странице, если данного атрибута у них нет. Значение атрибута установить равным значению атрибута alt.