ドット(.
)属性表記の代わりにsetAttribute
を使用することに関するベストプラクティスが開発されましたか?
例えば。:
myObj.setAttribute("className", "nameOfClass");
myObj.setAttribute("id", "someID");
または
myObj.className = "nameOfClass";
myObj.id = "someID";
JavaScriptでプログラムによるアクセスが必要な場合は、常に直接.attribute
フォームを使用する必要があります(ただし、以下のquirksmodeリンクを参照してください)。さまざまなタイプの属性を正しく処理する必要があります(「onload」と考えてください)。
DOMをそのまま処理する場合は、getAttribute
/setAttribute
を使用します(例:リテラルテキストのみ)。異なるブラウザーはこの2つを混同します。 Quirksモード:attribute(in)compatibility を参照してください。
Javascript:The Definitive Guide から、物事を明確にします。 HTMLElement HTMLドキュメントのオブジェクトは、すべての標準HTML属性に対応するJSプロパティを定義していることに注意してください。
したがって、非標準の属性に対してのみsetAttribute
を使用する必要があります。
例:
node.className = 'test'; // works
node.frameborder = '0'; // doesn't work - non standard attribute
node.setAttribute('frameborder', '0'); // works
これまでの回答はいずれも完全ではなく、ほとんどに誤情報が含まれています。
JavaScriptでDOM Element の属性にアクセスするには、3つの方法があります。これら3つはすべて、最新のブラウザーで使用方法を理解している限り、確実に機能します。
element.attributes
要素には、ライブ NamedNodeMap of Attr オブジェクトを返すプロパティ attributes があります。このコレクションのインデックスはブラウザによって異なる場合があります。そのため、順序は保証されません。 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>
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>
element.id
などのDOMオブジェクトのプロパティDOMオブジェクトの便利なプロパティを使用して、多くの属性にアクセスできます。存在する属性は、HTMLで定義されている属性ではなく、DOMノードのタイプによって異なります。プロパティは、問題のDOMオブジェクトのプロトタイプチェーンのどこかで定義されます。定義されている特定のプロパティは、アクセスしている要素のタイプによって異なります。たとえば、className
とid
はElement
で定義され、要素であるすべてのDOMノードに存在します(つまり、テキストノードまたはコメントノードではありません)。しかし、value
はより狭いです。 HTMLInputElement
で定義されており、他の要素には存在しない場合があります。
JavaScriptプロパティでは大文字と小文字が区別されることに注意してください。ほとんどのプロパティは小文字を使用しますが、一部はキャメルケースです。そのため、必ず仕様を確認してください
この「チャート」は、これらのDOMオブジェクトのプロトタイプチェーンの一部をキャプチャします。完全に近いものではありませんが、全体的な構造をキャプチャします。
____________Node___________
| | |
Element Text Comment
| |
HTMLElement SVGElement
| |
HTMLInputElement HTMLSpanElement
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>
警告:これは、HTML仕様がどのように定義し、最新のブラウザーが属性を処理するかの説明です。私は、古くて壊れたブラウザの制限に対処しようとしませんでした。古いブラウザをサポートする必要がある場合は、この情報に加えて、それらのブラウザで何が壊れているかを知る必要があります。
setAttribute
が必要なケースの1つは、対応するプロパティがないため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"
これらの答えは、実際にはpropertiesとattributesの間の大きな混乱に対処していません。また、Javascriptプロトタイプによっては、要素のプロパティを使用して属性にアクセスできる場合とできない場合があります。
まず、HTMLElement
はJavascriptオブジェクトであることを覚えておく必要があります。すべてのオブジェクトと同様に、プロパティがあります。もちろん、HTMLElement
の中に必要なほぼすべてのプロパティを作成できますが、DOM(ページ上にあるもの)で何もする必要はありません。ドット表記(.
)は、properties用です。現在、属性にマップされる特別なプロパティーがいくつかあります。また、現時点では、保証されているのは4つだけです(詳細は後述)。
すべてのHTMLElement
sには、attributes
というプロパティが含まれています。 HTMLElement.attributes
は、DOMの要素に関連するliveNamedNodeMap
オブジェクトです。 「ライブ」とは、DOMでノードが変更されると、JavaScript側でノードが変更され、その逆も同様であることを意味します。この場合、DOM属性は問題のノードです。 Node
には、変更可能な.nodeValue
プロパティがあります。 NamedNodeMap
オブジェクトには、ノード全体を変更できるsetNamedItem
という関数があります。キーでノードに直接アクセスすることもできます。例えば、.attributes.getNamedItem('dir');
と同じ.attributes["dir"]
と言うことができます(補足:NamedNodeMap
は大文字と小文字を区別しないため、'DIR'
を渡すこともできます)。
同様の関数がHTMLElement
に直接あり、そこでsetAttribute
を呼び出すことができます。これはノードを自動的に作成する存在しない場合はnodeValue
を設定します。また、特殊プロパティを介してHTMLElement
のプロパティとして直接アクセスできるsome属性(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 = newValue
element.attributes.ATTRIBUTENAME = newNode
element.attributes.setNamedItem(ATTRIBUTENAME) = newNode
結論(TL; DR)
HTMLElement
からの特別なプロパティマッピングを使用します:element.dir
、element.id
、element.className
、またはelement.lang
。
エレメントが特別なプロパティを持つ拡張HTMLElement
であることを100%確信している場合、その特別なマッピングを使用します。 (if (element instanceof HTMLAnchorElement)
で確認できます)。
属性がすでに存在することを100%確信している場合は、element.attributes.ATTRIBUTENAME.nodeValue = newValue
を使用します。
そうでない場合は、setAttribute()
を使用します。
「JavaScriptでsetAttribute vs .attribute =を使用するタイミング」
一般的なルールは、.attribute
を使用し、それがブラウザで動作するかどうかを確認することです。
..ブラウザで動作する場合は、準備完了です。
..そうでない場合は、that属性に.attribute
の代わりに.setAttribute(attribute, value)
を使用します。
すべての属性に対してリンスを繰り返します。
怠け者の場合は、.setAttribute
を使用できます。それはほとんどのブラウザでうまくいくはずです。 (.attribute
をサポートするブラウザは、.setAttribute(attribute, value)
よりも最適化できます。)
要素に属性(クラスなど)を設定するためのメソッド:1. el.className = string 2. el.setAttribute( 'class'、string)3. el.attributes.setNamedItem(object)4. el.setAttributeNode(node)
簡単なベンチマークテストを行いました( here )
また、setAttributeNodeはsetAttributeを使用した場合よりも約3倍高速であるようです。
パフォーマンスが問題になる場合-「setAttributeNode」を使用
これは、setAttributeを使用したほうが良い場合の1つです。
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);
}