Когда использовать 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. В основном, по порядку:
- Пользовательские свойства, потому что они не влияют на DOM и не являются атрибутами.
- Специальные отображения, предоставляемые браузером (
dir
, id
, className
). - Если атрибуты уже существуют,
element.attributes.ATTRIBUTENAME.nodeValue =
- SetAttribute();
- Если атрибуты уже существуют,
element.attributes.getNamedItem(ATTRIBUTENAME).nodeValue = newValue
-
element.attributes.ATTRIBUTENAME = newNode
-
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"