Когда использовать setAttribute vs .attribute = в JavaScript?

Имеет ли наилучшая практика использования setAttribute вместо нотации атрибута точки (.)?

Например:

myObj.setAttribute("className", "nameOfClass");
myObj.setAttribute("id", "someID");

или

myObj.className = "nameOfClass";
myObj.id = "someID";

Ответ 1

Вы всегда должны использовать прямую форму .attribute (но см. ссылку на quirksmode ниже), если вы хотите программный доступ в JavaScript. Он должен обрабатывать различные типы атрибутов (думаю, "загружать" ) правильно.

Используйте getAttribute/setAttribute, если вы хотите иметь дело с DOM как есть (например, только литерал). Различные браузеры путают два. См. Режимы Quirks: совместимость атрибутов (в).

Ответ 2

Из Javascript: окончательное руководство, он разъясняет вещи. Он отмечает, что HTMLElement объекты HTML doc определяют свойства JS, соответствующие всем стандартным атрибутам HTML.

Поэтому вам нужно использовать setAttribute для нестандартных атрибутов.

Пример:

node.className = 'test'; // works
node.frameborder = '0'; // doesn't work - non standard attribute
node.setAttribute('frameborder', '0'); // works

Ответ 3

Ни один из предыдущих ответов не является полным и большинство содержит дезинформацию.

Существует три способа доступа к атрибутам DOM Element в JavaScript. Все три работают надежно в современных браузерах, пока вы понимаете, как их использовать.

1. element.attributes

Элементы имеют свойство attributes, которое возвращает live NamedNodeMap объектов Attr. Индексы этой коллекции могут отличаться среди браузеров. Таким образом, заказ не гарантируется. NamedNodeMap имеет методы для добавления и удаления атрибутов (getNamedItem и setNamedItem, соответственно).

Обратите внимание, что, хотя XML явно чувствителен к регистру, спецификация DOM вызывает строковые имена для нормализации, поэтому имена, переданные в getNamedItem, являются эффективно нечувствителен к регистру.

Пример использования:

var div = document.getElementsByTagName('div')[0];

//you can look up specific attributes
var classAttr = div.attributes.getNamedItem('CLASS');
document.write('attributes.getNamedItem() Name: ' + classAttr.name + ' Value: ' + classAttr.value + '<br>');

//you can enumerate all defined attributes
for(var i = 0; i < div.attributes.length; i++) {
  var attr = div.attributes[i];
  document.write('attributes[] Name: ' + attr.name + ' Value: ' + attr.value + '<br>');
}

//create custom attribute
var customAttr = document.createAttribute('customTest');
customAttr.value = '567';
div.attributes.setNamedItem(customAttr);

//retreive custom attribute
customAttr = div.attributes.getNamedItem('customTest');
document.write('attributes.getNamedItem() Name: ' + customAttr.name + ' Value: ' + customAttr.value + '<br>');
<div class="class1" id="main" data-test="stuff" nonStandard="1234"></div>

Ответ 4

Один случай, когда я нашел, где setAttribute необходим, - это изменение атрибутов ARIA, поскольку соответствующих свойств нет. Например

x.setAttribute('aria-label', 'Test');
x.getAttribute('aria-label');

Там нет x.arialabel или что-то в этом роде, поэтому вам нужно использовать setAttribute.

Изменить: x [ "aria-label" ] не работает. Вам действительно нужен setAttribute.

x.getAttribute('aria-label')
null
x["aria-label"] = "Test"
"Test"
x.getAttribute('aria-label')
null
x.setAttribute('aria-label', 'Test2')
undefined
x["aria-label"]
"Test"
x.getAttribute('aria-label')
"Test2"

Ответ 5

"Когда использовать setAttribute vs .attribute = в JavaScript?"

Общее правило - использовать .attribute и проверить, работает ли он в браузере.

.. Если он работает в браузере, вам хорошо идти.

.. Если это не так, используйте .setAttribute(attribute, value) вместо .attribute для этого атрибута.

Повторите попытку повторения для всех атрибутов.

Хорошо, если вы ленивы, вы можете просто использовать .setAttribute. Это должно хорошо работать в большинстве браузеров. (Хотя браузеры, поддерживающие .attribute, могут оптимизировать его лучше, чем .setAttribute(attribute, value).)

Ответ 6

Это выглядит как один случай, когда лучше использовать setAttribute:

Dev.Opera - Эффективный JavaScript

var posElem = document.getElementById('animation');
var newStyle = 'background: ' + newBack + ';' +
'color: ' + newColor + ';' +
    'border: ' + newBorder + ';';
if(typeof(posElem.style.cssText) != 'undefined') {
    posElem.style.cssText = newStyle;
} else {
    posElem.setAttribute('style', newStyle);
}

Ответ 7

Эти ответы на самом деле не решают большую путаницу между свойствами и атрибутами. Кроме того, в зависимости от прототипа Javascript, иногда вы можете использовать свойство элемента для доступа к атрибутам, а иногда нет.

Во-первых, вы должны помнить, что HTMLElement - это объект Javascript. Как и все объекты, они имеют свойства. Конечно, вы можете создать свойство с именем почти все, что вы хотите внутри HTMLElement, но оно не имеет ничего общего с DOM (что на странице). Точечная запись (.) Предназначена для свойств. Теперь есть некоторые специальные свойства, которые сопоставляются с атрибутами, и на момент написания этой статьи гарантируется только 4 (подробнее об этом позже).

Все HTMLElement включают свойство под названием attributes. HTMLElement.attributes - это живой объект NamedNodeMap который относится к элементам в DOM. "Живой" означает, что когда узел изменяется в DOM, он изменяется на стороне JavaScript, и наоборот. Атрибутами DOM в данном случае являются рассматриваемые узлы. Node имеет свойство .nodeValue которое вы можете изменить. Объекты NamedNodeMap имеют функцию setNamedItem которой вы можете изменить весь узел. Вы также можете напрямую получить доступ к узлу с помощью ключа. Например, вы можете сказать .attributes["dir"] который совпадает с .attributes.getNamedItem('dir'); (Примечание: NamedNodeMap нечувствителен к регистру, поэтому вы также можете передать 'DIR');

Аналогичная функция есть прямо в HTMLElement где вы можете просто вызвать setAttribute который автоматически создаст узел, если он не существует, и установить nodeValue. Есть также некоторые атрибуты, к которым вы можете обращаться напрямую как к свойствам в HTMLElement через специальные свойства, такие как dir. Вот примерное отображение того, как это выглядит:

HTMLElement {
  attributes: {
    setNamedItem: function(attr, newAttr) { 
      this[attr] = newAttr;
    },    
    getNamedItem: function(attr) {
      return this[attr];
    },
    myAttribute1: {
      nodeName: 'myAttribute1',
      nodeValue: 'myNodeValue1'
    },
    myAttribute2: {
      nodeName: 'myAttribute2',
      nodeValue: 'myNodeValue2'
    },
  }
  setAttribute: function(attr, value) { 
    let item = this.attributes.getNamedItem(attr);
    if (!item) {
      item = document.createAttribute(attr);
      this.attributes.setNamedItem(attr, item);
    }
    item.nodeValue = value;
  },
  getAttribute: function(attr) { 
    return this.attributes[attr] && this.attributes[attr].nodeValue;
  },
  dir: // Special map to attributes.dir.nodeValue || ''
  id:  // Special map to attributes.id.nodeValue || ''
  className: // Special map to attributes.class.nodeValue || '' 
  lang: // Special map to attributes.lang.nodeValue || ''

}

Таким образом, вы можете изменить атрибуты dir 6 способами:

  // 1. Replace the node with setNamedItem
  const newAttribute = document.createAttribute('dir');
  newAttribute.nodeValue = 'rtl';
  element.attributes.setNamedItem(newAttribute);

  // 2. Replace the node by property name;
  const newAttribute2 = document.createAttribute('dir');
  newAttribute2.nodeValue = 'rtl';
  element.attributes['dir'] = newAttribute2;
  // OR
  element.attributes.dir = newAttribute2;

  // 3. Access node with getNamedItem and update nodeValue
  // Attribute must already exist!!!
  element.attributes.getNamedItem('dir').nodeValue = 'rtl';

  // 4. Access node by property update nodeValue
  // Attribute must already exist!!!
  element.attributes['dir'].nodeValue = 'rtl';
  // OR
  element.attributes.dir.nodeValue = 'rtl';

  // 5. use setAttribute()  
  element.setAttribute('dir', 'rtl');

  // 6. use the UNIQUELY SPECIAL dir property
  element["dir"] = 'rtl';
  element.dir = 'rtl';

Вы можете обновить все свойства с помощью методов # 1-5, но только с помощью метода # 6 только dir, id, lang и className.

Расширения HTMLElement

HTMLElement обладает этими 4 специальными свойствами. Некоторые элементы расширенных классов HTMLElement имеют еще более сопоставленные свойства. Например, HTMLAnchorElement имеет HTMLAnchorElement.href, HTMLAnchorElement.rel и HTMLAnchorElement.target. Но будьте осторожны, если вы установите эти свойства для элементов, которые не имеют этих специальных свойств (например, для HTMLTableElement), тогда атрибуты не изменятся, и они будут обычными обычными свойствами. Чтобы лучше понять, вот пример его наследования:

HTMLAnchorElement extends HTMLElement {
  // inherits all of HTMLElement
  href:    // Special map to attributes.href.nodeValue || ''
  target:  // Special map to attributes.target.nodeValue || ''
  rel:     // Special map to attributes.ref.nodeValue || '' 
}

Пользовательские свойства

Теперь большое предупреждение: как и все объекты Javascript, вы можете добавлять собственные свойства. Но это ничего не изменит в DOM. Ты можешь сделать:

  const newElement = document.createElement('div');
  // THIS WILL NOT CHANGE THE ATTRIBUTE
  newElement.display = 'block';

Но это так же, как

  newElement.myCustomDisplayAttribute = 'block';

Это означает, что добавление пользовательского свойства не будет связано с .attributes[attr].nodeValue.

Спектакль

Я создал тестовый пример jsperf, чтобы показать разницу: https://jsperf.com/set-attribute-comparison. В основном, по порядку:

  1. Пользовательские свойства, потому что они не влияют на DOM и не являются атрибутами.
  2. Специальные отображения, предоставляемые браузером (dir, id, className).
  3. Если атрибуты уже существуют, element.attributes.ATTRIBUTENAME.nodeValue =
  4. SetAttribute();
  5. Если атрибуты уже существуют, element.attributes.getNamedItem(ATTRIBUTENAME).nodeValue = newValue
  6. element.attributes.ATTRIBUTENAME = newNode
  7. element.attributes.setNamedItem(ATTRIBUTENAME) = newNode

Вывод (TL; DR)

  • Используйте специальные сопоставления свойств из HTMLElement: element.dir, element.id, element.className или element.lang.

  • Если вы на 100% уверены, что элемент является расширенным HTMLElement со специальным свойством, используйте это специальное сопоставление. (Вы можете проверить с помощью if (element instanceof HTMLAnchorElement)).

  • Если вы на 100% уверены, что атрибут уже существует, используйте element.attributes.ATTRIBUTENAME.nodeValue = newValue.

  • Если нет, используйте setAttribute().

Ответ 8

методы для установки атрибутов (например, класса) для элемента: 1. el.className = строка 2. el.setAttribute( "класс", строка) 3. el.attributes.setNamedItem(объект) 4. el.setAttributeNode(node)

Я сделал простой тестовый тест (здесь)

и кажется, что setAttributeNode примерно в 3 раза быстрее, чем при использовании setAttribute.

поэтому, если производительность является проблемой, используйте "setAttributeNode"