Работа с атрибутами и свойствами элементов в JavaScript

Содержание:
  1. Чем отличается атрибут от DOM-свойства
  2. Работа с DOM-свойствами элемента
  3. Атрибуты элементов и методы для работы с ними
  4. Ещё один способ работы с атрибутами (свойство attributes)
  5. Задачи
  6. Комментарии

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

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

Атрибуты — это HTML-сущности, с помощью которых мы можем добавить определённые данные к элементам в HTML-коде.

Когда браузер запрашивает некоторую страницу, он получает её исходный 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-свойств могут быть различными. Т.е. атрибут может иметь одно значение, а DOM-свойство, созданное на его основе – другое.

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

<input type="checkbox" checked>

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

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

<input type="checkbox">

Кроме этого, JavaScript позволяет также работать с атрибутами. Для этого в DOM API имеются специальные методы. Но их желательно использовать только тогда, когда вам действительно нужно работать с данными именно так.

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

Основные отличия между DOM-свойствами и атрибутами:

  • значение атрибута – это всегда строка, а значение DOM-свойства – определённый тип данных (не обязательно строка);
  • имя атрибута – регистронезависимо, а DOM-свойства - регистрозависимо. Т.е. в HTML-коде мы можем, например, HTML-атрибут id написать, как Id, ID и т.д. То же касается и имени атрибута, которые мы указываем в специальных методах JavaScript для работы с ним. Но к соответствующему 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-свойств, как это уже было отмечено выше всегда является строкой.

В 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>

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

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

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

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

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

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

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

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

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

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

name.defaultValue; // Tom

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

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

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

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

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

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

Поэтому если нам нужно получить то, что находится в атрибуте, то без метода 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>

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

В JavaScript у каждого элемента имеется свойство attributes, с помощью которого можно получить все его атрибуты в виде объекта 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>

Задачи

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

Комментарии: 5

Amsterdam
Amsterdam

Александр, добрый день!

Не подскажите, возможно ли установить элементу несколько атрибутов (не css стили, а именно html параметры) в одну строку? Например:

document.getElementById('range').setAttribute('value', '50000')
document.getElementById('range').setAttribute('min', '50000')

Хотелось бы реализовать по такому типу:

document.getElementById('range').setAttribute('min', '50000'; 'value', '50000')

но так не работает..

Александр Мальцев
Александр Мальцев

Привет!

Только если написать вспомогательную функцию:
function setAttributes(el, attrs) {
  for(var key in attrs) {
    el.setAttribute(key, attrs[key]);
  }
}
Потом использовать так:
setAttributes(document.getElementById('range'), {'min': '50000', 'value': '50000'});
Oleg
Oleg
Здравствуйте. А как можно получить доступ к атрибуту checked элемента input с type, равным checkbox.
Метод getAttribute('checked') возвращает null, хотя такой атрибут у элемента есть.
Александр Мальцев
Александр Мальцев
Здравствуйте!
Когда браузер читает HTML документ, он генерирует на её основе DOM. При этом все стандартные атрибуты становятся DOM-свойствами. При этом атрибуты и DOM-свойства хоть на первый взгляд кажутся похожими, но это не одно и тоже.
Т.е. изначально вы создали в HTML-документе элемент:
<input id="my-checkbox" type="checkbox">
Когда браузер прочитал этот код, он создал в DOM элемент input и свойству checked установил значение false. Но значение атрибута осталось без изменений. Вот такая особенность.
В этом случае чтобы узнать его состояние, нам нужно обратиться именно к DOM-свойству элемента:
console.log(document.querySelector('#my-checkbox').checked); //false
Если же мы обратимся к значению атрибута checked, то получим null. Т.к. у элемента данного атрибута нет:
console.log(document.querySelector('#my-checkbox').getAttribute('checked')); // null
Теперь если мы нажмём на него, мы изменим его состояние на true (его свойство):
console.log(document.querySelector('#my-checkbox').checked); //true
Но на атрибут это изменение браузер не отобразит, т.к. уж особенность:
console.log(document.querySelector('#my-checkbox').getAttribute('checked')); // null
Просто у нас есть 2 разные вещи: DOM-свойства и атрибуты. Это не одно и тоже.
При этом состояние checked правильно получать посредством DOM-свойства checked.

Например, если провести эксперимент дальше и, например в HTML-документе создать следующий код:
<input id="my-checkbox" type="checkbox" checked>
Т.е. сразу установить checkbox во включенное состояние.
При этом, получая DOM-свойство checked данного элемента, вы получите true:
console.log(document.querySelector('#my-checkbox').checked); //true
А получая значение атрибута checked, вы получите пустую строку:
console.log(document.querySelector('#my-checkbox').getAttribute('checked')); // ""
Oleg
Oleg
Огромное спасибо за столь исчерпывающий ответ!!!