Имеет ли наилучшая практика использования setAttribute вместо нотации атрибута точки (.)?
Например:
myObj.setAttribute("className", "nameOfClass");
myObj.setAttribute("id", "someID");
или
myObj.className = "nameOfClass";
myObj.id = "someID";
Имеет ли наилучшая практика использования setAttribute вместо нотации атрибута точки (.)?
Например:
myObj.setAttribute("className", "nameOfClass");
myObj.setAttribute("id", "someID");
или
myObj.className = "nameOfClass";
myObj.id = "someID";
Вы всегда должны использовать прямую форму .attribute (но см. ссылку на quirksmode ниже), если вы хотите программный доступ в JavaScript. Он должен обрабатывать различные типы атрибутов (думаю, "загружать" ) правильно.
Используйте getAttribute/setAttribute, если вы хотите иметь дело с DOM как есть (например, только литерал). Различные браузеры путают два. См. Режимы Quirks: совместимость атрибутов (в).
Из 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
Ни один из предыдущих ответов не является полным и большинство содержит дезинформацию.
Существует три способа доступа к атрибутам DOM Element в JavaScript. Все три работают надежно в современных браузерах, пока вы понимаете, как их использовать.
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> Один случай, когда я нашел, где 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"
"Когда использовать setAttribute vs .attribute = в JavaScript?"
Общее правило - использовать .attribute и проверить, работает ли он в браузере.
.. Если он работает в браузере, вам хорошо идти.
.. Если это не так, используйте .setAttribute(attribute, value) вместо .attribute для этого атрибута.
Повторите попытку повторения для всех атрибутов.
Хорошо, если вы ленивы, вы можете просто использовать .setAttribute. Это должно хорошо работать в большинстве браузеров. (Хотя браузеры, поддерживающие .attribute, могут оптимизировать его лучше, чем .setAttribute(attribute, value).)
Это выглядит как один случай, когда лучше использовать 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);
}
Эти ответы на самом деле не решают большую путаницу между свойствами и атрибутами. Кроме того, в зависимости от прототипа 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 обладает этими 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. В основном, по порядку:
dir, id, className).element.attributes.ATTRIBUTENAME.nodeValue =element.attributes.getNamedItem(ATTRIBUTENAME).nodeValue = newValueelement.attributes.ATTRIBUTENAME = newNodeelement.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().
методы для установки атрибутов (например, класса) для элемента: 1. el.className = строка 2. el.setAttribute( "класс", строка) 3. el.attributes.setNamedItem(объект) 4. el.setAttributeNode(node)
Я сделал простой тестовый тест (здесь)
и кажется, что setAttributeNode примерно в 3 раза быстрее, чем при использовании setAttribute.
поэтому, если производительность является проблемой, используйте "setAttributeNode"