IT story

JavaScript에서 setAttribute vs.attribute =를 사용하는시기

hot-time 2020. 5. 6. 21:08
반응형

JavaScript에서 setAttribute vs.attribute =를 사용하는시기


setAttribute도트 ( .) 속성 표기법 대신 사용에 대한 모범 사례 가 개발 되었습니까?

예 :

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

또는

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

.attributeJavaScript로 프로그래밍 방식으로 액세스하려면 항상 직접 양식을 사용해야합니다 (그러나 아래의 quirksmode 링크 참조). 다른 유형의 속성 ( "onload"라고 생각)을 올바르게 처리해야합니다.

DOM을 그대로 처리 하려면 getAttribute/를 사용하십시오 setAttribute(예 : 리터럴 텍스트 만). 다른 브라우저는 두 가지를 혼동합니다. Quirks modes : attribute (in) compatibility를 참조하십시오 .


에서 자바 스크립트 : 확실한 가이드 , 그것은 일을 명확히. 그것은 있다고 지적 는 HTMLElement는 모든 표준 HTML에 해당하는 속성이 있다는 JS 속성을 정의한 HTML의 문서의 객체.

따라서 setAttribute비표준 속성 에만 사용해야 합니다.

예:

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

이전 답변 중 어느 것도 완전하지 않으며 대부분 잘못된 정보를 포함합니다.

JavaScript에서 DOM 요소 의 속성에 액세스하는 세 가지 방법이 있습니다 . 세 가지 방법 모두 사용 방법을 이해하는 한 최신 브라우저에서 안정적으로 작동합니다.

1. element.attributes

요소는 속성이 속성을 라이브 그 반환 NamedNodeMap입니다Attr의이 객체를. 이 컬렉션의 색인은 브라우저마다 다를 수 있습니다. 따라서 주문이 보장되지 않습니다. NamedNodeMap속성을 추가하고 제거하는 방법이 있습니다 ( 각각, getNamedItemsetNamedItem

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>

2. element.getAttribute&element.setAttribute

이러한 메소드 Element는 액세스 할 필요없이 메소드와 메소드에 직접 존재 attributes하지만 동일한 기능을 수행합니다.

문자열 이름은 대소 문자를 구분하지 않습니다.

사용법 예 :

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. DOM 객체의 속성 (예 : element.id

DOM 객체의 편리한 속성을 사용하여 많은 속성에 액세스 할 수 있습니다. 존재하는 속성은 HTML에 정의 된 속성이 아니라 DOM 노드의 유형에 따라 다릅니다. 속성은 해당 DOM 객체의 프로토 타입 체인에 정의되어 있습니다. 정의 된 특정 속성은 액세스중인 요소 유형에 따라 다릅니다. 예를 들어, classNameid에 정의 Element및 요소 (예.하지 텍스트 또는 주석 노드) 모든 DOM 노드에 존재합니다. 그러나 value더 좁습니다. HTMLInputElement다른 요소에 정의되어 있지 않을 수도 있습니다.

JavaScript 속성은 대소 문자를 구분합니다. 대부분의 속성은 소문자를 사용하지만 일부는 camelCase입니다. 따라서 항상 사양을 확인하십시오.

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.

                      ____________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.


One case I found where setAttribute is necessary is when changing ARIA attributes, since there are no corresponding properties. For example

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

There's no x.arialabel or anything like that, so you have to use setAttribute.

Edit: x["aria-label"] does not work. You really do need 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"

"When to use setAttribute vs .attribute= in JavaScript?"

A general rule is to use .attribute and check if it works on the browser.

..If it works on the browser, you're good to go.

..If it doesn't, use .setAttribute(attribute, value) instead of .attribute for that 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).)


These answers aren't really addressing the large confusion with between properties and 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.

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 properties that are mapped to attributes, and at the time or writing there are only 4 that are guaranteed (more on that later).

All HTMLElements include a property called attributes. HTMLElement.attributes is a live NamedNodeMap 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');

There's a similar function directly in HTMLElement where you can just call setAttribute which will automatically create a node if it doesn't exist and set the nodeValue. There are also some attributes 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 {
  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:

  // 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.

Extensions of 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:

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:

  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.

Performance

I've built a jsperf test case to show the difference: https://jsperf.com/set-attribute-comparison. Basically, In order:

  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

Conclusion (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 HTMLElement with 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().


This looks like one case where it is better to use 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);
}

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)

I have made a simple benchmark test (here)

and it seems that setAttributeNode is about 3 times faster then using setAttribute.

so if performance is an issue - use "setAttributeNode"

참고URL : https://stackoverflow.com/questions/3919291/when-to-use-setattribute-vs-attribute-in-javascript

반응형