何时在 JavaScript 中使用 setAttribute 与 .attribute= ?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/3919291/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
When to use setAttribute vs .attribute= in JavaScript?
提问by Francisc
Has a best-practice around using setAttribute
instead of the dot (.
) attribute notation been developed?
是否开发了使用setAttribute
而不是点 ( .
) 属性符号的最佳实践?
E.g.:
例如:
myObj.setAttribute("className", "nameOfClass");
myObj.setAttribute("id", "someID");
or
或者
myObj.className = "nameOfClass";
myObj.id = "someID";
采纳答案by Ben
You should always use the direct .attribute
form (but see the quirksmode link below) if you want programmatic access in JavaScript. It should handle the different types of attributes (think "onload") correctly.
.attribute
如果您希望在 JavaScript 中进行编程访问,则应始终使用直接形式(但请参阅下面的 quirksmode 链接)。它应该正确处理不同类型的属性(想想“onload”)。
Use getAttribute
/setAttribute
when you wish to deal with the DOM as it is (e.g. literal text only). Different browsers confuse the two. See Quirks modes: attribute (in)compatibility.
当您希望按原样处理 DOM(例如仅文本)时,请使用getAttribute
/ setAttribute
。不同的浏览器将两者混淆。请参阅Quirks 模式:attribute (in)compatibility。
回答by olan
From Javascript: The Definitive Guide, it clarifies things. It notes that HTMLElementobjects of a HTML doc define JS properties that correspond to all standard HTML attributes.
来自Javascript: The Definitive Guide,它澄清了一些事情。它指出HTML 文档的HTMLElement对象定义了对应于所有标准 HTML 属性的 JS 属性。
So you only need to use setAttribute
for non-standard attributes.
所以你只需要setAttribute
用于非标准属性。
Example:
例子:
node.className = 'test'; // works
node.frameborder = '0'; // doesn't work - non standard attribute
node.setAttribute('frameborder', '0'); // works
回答by Ben
None of the previous answers are complete and most contain misinformation.
以前的答案都不完整,而且大多数都包含错误信息。
There are three ways of accessing the attributes of a DOM Elementin JavaScript. All three work reliably in modern browsers as long as you understand how to utilize them.
在 JavaScript 中可以通过三种方式访问 DOM元素的属性。只要您了解如何使用它们,这三者都可以在现代浏览器中可靠地工作。
1. element.attributes
1. element.attributes
Elements have a property attributesthat returns a live NamedNodeMapof Attrobjects. The indexes of this collection may be different among browsers. So, the order is not guaranteed. NamedNodeMap
has methods for adding and removing attributes (getNamedItem
and setNamedItem
, respectively).
元素具有返回Attr对象的活动NamedNodeMap的属性属性。此集合的索引可能因浏览器而异。因此,不能保证顺序。具有添加和删除属性的方法(分别为和)。NamedNodeMap
getNamedItem
setNamedItem
Notice that though XML is explicitly case sensitive, the DOM spec calls for string names to be normalized, so names passed to getNamedItem
are effectively case insensitive.
请注意,尽管 XML 明确区分大小写,但 DOM 规范要求将字符串名称规范化,因此传递给的名称getNamedItem
实际上不区分大小写。
Example Usage:
示例用法:
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>
2. element.getAttribute
& element.setAttribute
2. element.getAttribute
&element.setAttribute
These methods exist directly on the Element
without needing to access attributes
and its methods but perform the same functions.
这些方法直接存在于Element
不需要访问的地方attributes
,它的方法却执行相同的功能。
Again, notice that string name are case insensitive.
再次注意,字符串名称不区分大小写。
Example Usage:
示例用法:
var div = document.getElementsByTagName('div')[0];
//get specific attributes
document.write('Name: class Value: ' + div.getAttribute('class') + '<br>');
document.write('Name: ID Value: ' + div.getAttribute('ID') + '<br>');
document.write('Name: DATA-TEST Value: ' + div.getAttribute('DATA-TEST') + '<br>');
document.write('Name: nonStandard Value: ' + div.getAttribute('nonStandard') + '<br>');
//create custom attribute
div.setAttribute('customTest', '567');
//retreive custom attribute
document.write('Name: customTest Value: ' + div.getAttribute('customTest') + '<br>');
<div class="class1" id="main" data-test="stuff" nonStandard="1234"></div>
3. Properties on the DOM object, such as element.id
3. DOM 对象上的属性,如 element.id
Many attributes can be accessed using convenient properties on the DOM object. Which attributes exist depends on the DOM node's type, not which attributes are defined in the HTML. The properties are defined somewhere in the prototype chain of DOM object in question. The specific properties defined will depend on the type of Element you are accessing. For example, className
and id
are defined on Element
and exist on all DOM nodes that are elements (ie. not text or comment nodes). But value
is more narrow. It's defined on HTMLInputElement
and may not exist on other elements.
可以使用 DOM 对象上的便捷属性访问许多属性。哪些属性存在取决于 DOM 节点的类型,而不是 HTML 中定义的哪些属性。这些属性在所讨论的 DOM 对象的原型链中的某处定义。定义的特定属性将取决于您正在访问的元素类型。例如,className
与id
被定义Element
和存在是元件(即,不文本或注释节点)的所有DOM节点上。但是value
比较窄。它是HTMLInputElement
在其他元素上定义的,可能不存在于其他元素上。
Notice that JavaScript properties are case sensitive. Although most properties will use lowercase, some are camelCase. So always check the spec to be sure.
请注意,JavaScript 属性区分大小写。尽管大多数属性将使用小写字母,但也有一些是驼峰式的。因此,请务必检查规范。
This "chart" captures a portion of the prototype chain for these DOM objects. It's not even close to complete, but it captures the overall structure.
这个“图表”捕获了这些 DOM 对象的原型链的一部分。它甚至还没有接近完成,但它捕获了整体结构。
____________Node___________
| | |
Element Text Comment
| |
HTMLElement SVGElement
| |
HTMLInputElement HTMLSpanElement
Example Usage:
示例用法:
var div = document.getElementsByTagName('div')[0];
//get specific attributes
document.write('Name: class Value: ' + div.className + '<br>');
document.write('Name: id Value: ' + div.id + '<br>');
document.write('Name: ID Value: ' + div.ID + '<br>'); //undefined
document.write('Name: data-test Value: ' + div.dataset.test + '<br>'); //.dataset is a special case
document.write('Name: nonStandard Value: ' + div.nonStandard + '<br>'); //undefined
<div class="class1" id="main" data-test="stuff" nonStandard="1234"></div>
Caveat: This is an explanation of how the HTML spec defines and modern browsers handle attributes. I did not attempt to deal with limitations of ancient, broken browsers. If you need to support old browsers, in addition to this information, you will need to know what is broken in the those browsers.
警告:这是对 HTML 规范如何定义和现代浏览器处理属性的解释。我没有试图处理古老的、损坏的浏览器的局限性。如果您需要支持旧浏览器,除了这些信息之外,您还需要知道这些浏览器中的哪些问题。
回答by Antimony
One case I found where setAttribute
is necessary is when changing ARIA attributes, since there are no corresponding properties. For example
我发现setAttribute
有必要的一种情况是更改 ARIA 属性时,因为没有相应的属性。例如
x.setAttribute('aria-label', 'Test');
x.getAttribute('aria-label');
There's no x.arialabel
or anything like that, so you have to use setAttribute.
没有x.arialabel
或类似的东西,所以你必须使用 setAttribute。
Edit: x["aria-label"] does not work. You really do need 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"
回答by ShortFuse
These answers aren't really addressing the large confusion with between propertiesand attributes. Also, depending on the Javascript prototype, sometimes you can use a an element's property to access an attributes and sometimes you can't.
这些答案并没有真正解决properties和attributes之间的巨大混淆。此外,根据 Javascript 原型,有时您可以使用元素的属性来访问属性,有时则不能。
First, you have to remember that an HTMLElement
is a Javascript object. Like all objects, they have properties. Sure, you can create a property called nearly anything you want inside HTMLElement
, but it doesn't have to do anything with the DOM (what's on the page). The dot notation (.
) is for properties. Now, there some special propertiesthat are mapped to attributes, and at the time or writing there are only 4 that are guaranteed (more on that later).
首先,您必须记住 anHTMLElement
是一个 Javascript 对象。像所有对象一样,它们具有属性。当然,您可以在内部创建一个几乎任何您想要的名称的属性HTMLElement
,但它不必对 DOM(页面上的内容)做任何事情。点符号 ( .
) 用于属性。现在,有一些特殊的属性映射到属性,并在当时或写,只有4所保证的(稍后更多)。
All HTMLElement
s include a property called attributes
. HTMLElement.attributes
is a liveNamedNodeMap
Object that relates to the elements in the DOM. "Live" means that when the node changes in the DOM, they change on the JavaScript side, and vice versa. DOM attributes, in this case, are the nodes in question. A Node
has a .nodeValue
property that you can change. NamedNodeMap
objects have a function called setNamedItem
where you can change the entire node. You can also directly access the node by the key. For example, you can say .attributes["dir"]
which is the same as .attributes.getNamedItem('dir');
(Side note, NamedNodeMap
is case-insensitive, so you can also pass 'DIR'
);
所有HTMLElement
s 都包含一个名为 的属性attributes
。HTMLElement.attributes
是一个与 DOM 中的元素相关的活动NamedNodeMap
对象。“活”意味着当节点在 DOM 中发生变化时,它们在 JavaScript 端发生变化,反之亦然。在这种情况下,DOM 属性是有问题的节点。ANode
具有.nodeValue
您可以更改的属性。NamedNodeMap
对象有一个函数setNamedItem
,您可以在其中更改整个节点。也可以通过key直接访问节点。例如,您可以说.attributes["dir"]
which 与.attributes.getNamedItem('dir');
(Side note, NamedNodeMap
is case-insensitive, so you can pass 'DIR'
);
There's a similar function directly in HTMLElement
where you can just call setAttribute
which will automatically create a nodeif it doesn't exist and set the nodeValue
. There are also someattributes you can access directly as properties in HTMLElement
via special properties, such as dir
. Here's a rough mapping of what it looks like:
直接有一个类似的函数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 || ''
}
So you can change the dir
attributes 6 ways:
因此,您可以通过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';
You can update all properties with methods #1-5, but only dir
, id
, lang
, and className
with method #6.
您可以更新方法#1-5的所有属性,但只dir
,id
,lang
,并className
与方法#6。
Extensions of HTMLElement
HTMLElement 的扩展
HTMLElement
has those 4 special properties. Some elements are extended classes of HTMLElement
have even more mapped properties. For example, HTMLAnchorElement
has HTMLAnchorElement.href
, HTMLAnchorElement.rel
, and HTMLAnchorElement.target
. But, beware, if you set those properties on elements that do not have those special properties (like on a HTMLTableElement
) then the attributes aren't changed and they are just, normal custom properties. To better understand, here's an example of its inheritance:
HTMLElement
有这 4 个特殊属性。一些元素是HTMLElement
具有更多映射属性的扩展类。例如,HTMLAnchorElement
有HTMLAnchorElement.href
,HTMLAnchorElement.rel
和HTMLAnchorElement.target
。但是,请注意,如果您在没有这些特殊属性的元素上设置这些属性(例如在 a 上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 || ''
}
Custom Properties
自定义属性
Now the big warning: Like all Javascript objects, you can add custom properties. But, those won't change anything on the DOM. You can do:
现在最大的警告是:像所有 Javascript 对象一样,您可以添加自定义属性。但是,这些不会改变 DOM 上的任何内容。你可以做:
const newElement = document.createElement('div');
// THIS WILL NOT CHANGE THE ATTRIBUTE
newElement.display = 'block';
But that's the same as
但这与
newElement.myCustomDisplayAttribute = 'block';
This means that adding a custom property will not be linked to .attributes[attr].nodeValue
.
这意味着添加自定义属性不会链接到.attributes[attr].nodeValue
.
Performance
表现
I've built a jsperf test case to show the difference: https://jsperf.com/set-attribute-comparison. Basically, In order:
我已经构建了一个 jsperf 测试用例来显示差异:https://jsperf.com/set-attribute-comparison。基本上,按顺序:
- Custom properties because they don't affect the DOM and are not attributes.
- Special mappings provided by the browser (
dir
,id
,className
). - If attributes already exists,
element.attributes.ATTRIBUTENAME.nodeValue =
- setAttribute();
- If attributes already exists,
element.attributes.getNamedItem(ATTRIBUTENAME).nodeValue = newValue
element.attributes.ATTRIBUTENAME = newNode
element.attributes.setNamedItem(ATTRIBUTENAME) = newNode
- 自定义属性,因为它们不影响 DOM 并且不是 attributes。
- 浏览器提供的特殊映射 (
dir
,id
,className
)。 - 如果属性已经存在,
element.attributes.ATTRIBUTENAME.nodeValue =
- 设置属性();
- 如果属性已经存在,
element.attributes.getNamedItem(ATTRIBUTENAME).nodeValue = newValue
element.attributes.ATTRIBUTENAME = newNode
element.attributes.setNamedItem(ATTRIBUTENAME) = newNode
Conclusion (TL;DR)
结论 (TL; DR)
Use the special property mappings from
HTMLElement
:element.dir
,element.id
,element.className
, orelement.lang
.If you are 100% sure the element is an extended
HTMLElement
with a special property, use that special mapping. (You can check withif (element instanceof HTMLAnchorElement)
).If you are 100% sure the attribute already exists, use
element.attributes.ATTRIBUTENAME.nodeValue = newValue
.If not, use
setAttribute()
.
从使用特殊的属性映射
HTMLElement
:element.dir
,element.id
,element.className
,或element.lang
。如果您 100% 确定该元素是
HTMLElement
具有特殊属性的扩展,请使用该特殊映射。(您可以使用 进行检查if (element instanceof HTMLAnchorElement)
)。如果您 100% 确定该属性已存在,请使用
element.attributes.ATTRIBUTENAME.nodeValue = newValue
.如果没有,请使用
setAttribute()
.
回答by Pacerier
"When to use setAttribute vs .attribute= in JavaScript?"
“什么时候在 JavaScript 中使用 setAttribute 和 .attribute=?”
A general rule is to use .attribute
and check if it works on the browser.
一般规则是使用.attribute
并检查它是否适用于浏览器。
..If it works on the browser, you're good to go.
..如果它适用于浏览器,你就可以开始了。
..If it doesn't, use .setAttribute(attribute, value)
instead of .attribute
for thatattribute.
..如果没有,使用.setAttribute(attribute, value)
,而不是.attribute
用于该属性。
Rinse-repeat for all attributes.
对所有属性重复冲洗。
Well, if you're lazy you can simply use .setAttribute
. That should work fine on most browsers. (Though browsers that support .attribute
can optimize it better than .setAttribute(attribute, value)
.)
好吧,如果你很懒,你可以简单地使用.setAttribute
. 这应该适用于大多数浏览器。(虽然支持的浏览器.attribute
比.setAttribute(attribute, value)
.
回答by Yair Levy
methods for setting attributes(for example class) on an element: 1. el.className = string 2. el.setAttribute('class',string) 3. el.attributes.setNamedItem(object) 4. el.setAttributeNode(node)
在元素上设置属性(例如类)的方法: 1. el.className = string 2. el.setAttribute('class',string) 3. el.attributes.setNamedItem(object) 4. el.setAttributeNode(node)
I have made a simple benchmark test (here)
我做了一个简单的基准测试(这里)
and it seems that setAttributeNode is about 3 times faster then using setAttribute.
似乎 setAttributeNode 比使用 setAttribute 快大约 3 倍。
so if performance is an issue - use "setAttributeNode"
所以如果性能是一个问题 - 使用“setAttributeNode”
回答by Maxim Mazurok
Interesting takeout from Google API scriptregarding this:
谷歌 API 脚本中关于此的有趣内容:
They do it like this:
他们这样做:
var scriptElement = document.createElement("script");
scriptElement = setAttribute("src", "https://some.com");
scriptElement = setAttribute("nonce", "https://some.com");
scriptElement.async = "true";
Notice, how they use setAttribute
for "src" and "nonce", but then .async = ...
for "async" attribute.
请注意,它们如何setAttribute
用于“src”和“nonce”,然后.async = ...
用于“async”属性。
I'm not 100% sure, but probably that's because "async" is only supported on browsers that support direct .attr =
assignment. So, there's no sense trying to sestAttribute("async")
because if browser doesn't understand .async=...
- it will not understand "async" attribute.
我不是 100% 确定,但这可能是因为“异步”仅在支持直接.attr =
分配的浏览器上受支持。所以,尝试是没有意义的,sestAttribute("async")
因为如果浏览器不理解.async=...
- 它不会理解“async”属性。
Hopefully, that's a helpful insight from my ongoing "Un-minify GAPI"research project. Correct me if I'm wrong.
希望这是我正在进行的“Un-minify GAPI”研究项目的有用见解。如果我错了纠正我。
回答by tomo7
This looks like one case where it is better to use setAttribute:
这看起来像是最好使用 setAttribute 的一种情况:
Dev.Opera — Efficient 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);
}