何时在 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

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-23 06:38:20  来源:igfitidea点击:

When to use setAttribute vs .attribute= in JavaScript?

javascriptattributessetattribute

提问by Francisc

Has a best-practice around using setAttributeinstead 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 .attributeform (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/setAttributewhen 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 setAttributefor 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. NamedNodeMaphas methods for adding and removing attributes (getNamedItemand setNamedItem, respectively).

元素具有返回Attr对象的活动NamedNodeMap的属性属性。此集合的索引可能因浏览器而异。因此,不能保证顺序。具有添加和删除属性的方法(分别为和)。NamedNodeMapgetNamedItemsetNamedItem

Notice that though XML is explicitly case sensitive, the DOM spec calls for string names to be normalized, so names passed to getNamedItemare 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 Elementwithout needing to access attributesand 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, classNameand idare defined on Elementand exist on all DOM nodes that are elements (ie. not text or comment nodes). But valueis more narrow. It's defined on HTMLInputElementand may not exist on other elements.

可以使用 DOM 对象上的便捷属性访问许多属性。哪些属性存在取决于 DOM 节点的类型,而不是 HTML 中定义的哪些属性。这些属性在所讨论的 DOM 对象的原型链中的某处定义。定义的特定属性将取决于您正在访问的元素类型。例如,classNameid被定义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 setAttributeis 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.arialabelor 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.

这些答案并没有真正解决propertiesattributes之间的巨大混淆。此外,根据 Javascript 原型,有时您可以使用元素的属性来访问属性,有时则不能。

First, you have to remember that an HTMLElementis 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 HTMLElements include a property called attributes. HTMLElement.attributesis a liveNamedNodeMapObject 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 Nodehas a .nodeValueproperty that you can change. NamedNodeMapobjects have a function called setNamedItemwhere 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, NamedNodeMapis case-insensitive, so you can also pass 'DIR');

所有HTMLElements 都包含一个名为 的属性attributesHTMLElement.attributes是一个与 DOM 中的元素相关的活动NamedNodeMap对象。“活”意味着当节点在 DOM 中发生变化时,它们在 JavaScript 端发生变化,反之亦然。在这种情况下,DOM 属性是有问题的节点。ANode具有.nodeValue您可以更改的属性。NamedNodeMap对象有一个函数setNamedItem,您可以在其中更改整个节点。也可以通过key直接访问节点。例如,您可以说.attributes["dir"]which 与.attributes.getNamedItem('dir');(Side note, NamedNodeMapis case-insensitive, so you can pass 'DIR');

There's a similar function directly in HTMLElementwhere you can just call setAttributewhich will automatically create a nodeif it doesn't exist and set the nodeValue. There are also someattributes you can access directly as properties in HTMLElementvia 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 dirattributes 6 ways:

因此,您可以通过dir6 种方式更改属性:

  // 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 classNamewith method #6.

您可以更新方法#1-5的所有属性,但只diridlang,并className与方法#6。

Extensions of HTMLElement

HTMLElement 的扩展

HTMLElementhas those 4 special properties. Some elements are extended classes of HTMLElementhave even more mapped properties. For example, HTMLAnchorElementhas 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具有更多映射属性的扩展类。例如,HTMLAnchorElementHTMLAnchorElement.hrefHTMLAnchorElement.relHTMLAnchorElement.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。基本上,按顺序:

  1. Custom properties because they don't affect the DOM and are not attributes.
  2. Special mappings provided by the browser (dir, id, className).
  3. If attributes already exists, element.attributes.ATTRIBUTENAME.nodeValue =
  4. setAttribute();
  5. If attributes already exists, element.attributes.getNamedItem(ATTRIBUTENAME).nodeValue = newValue
  6. element.attributes.ATTRIBUTENAME = newNode
  7. element.attributes.setNamedItem(ATTRIBUTENAME) = newNode
  1. 自定义属性,因为它们不影响 DOM 并且不是 attributes
  2. 浏览器提供的特殊映射 ( dir, id, className)。
  3. 如果属性已经存在element.attributes.ATTRIBUTENAME.nodeValue =
  4. 设置属性();
  5. 如果属性已经存在element.attributes.getNamedItem(ATTRIBUTENAME).nodeValue = newValue
  6. element.attributes.ATTRIBUTENAME = newNode
  7. element.attributes.setNamedItem(ATTRIBUTENAME) = newNode

Conclusion (TL;DR)

结论 (TL; DR)

  • Use the special property mappings from HTMLElement: element.dir, element.id, element.className, or element.lang.

  • If you are 100% sure the element is an extended HTMLElementwith a special property, use that special mapping. (You can check with if (element instanceof HTMLAnchorElement)).

  • If you are 100% sure the attribute already exists, use element.attributes.ATTRIBUTENAME.nodeValue = newValue.

  • If not, use setAttribute().

  • 从使用特殊的属性映射HTMLElementelement.direlement.idelement.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 .attributeand 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 .attributefor 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 .attributecan 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 setAttributefor "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

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);
}