JavaScript'te setAttribute vs .attribute = ne zaman kullanılır?


234

setAttributeDot ( .) özellik gösterimi yerine kullanım konusunda en iyi uygulama geliştirildi mi?

Örneğin:

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

veya

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

1
Ben den açıldığında .setAttribute()için [key] = value, her şey çalışma sihirli başladı.
Andrew

Yanıtlar:


73

.attributeJavaScript'te programlı erişim istiyorsanız her zaman doğrudan formu kullanmalısınız (ancak aşağıdaki quirksmode bağlantısına bakın). Farklı nitelik türlerini ("yük") düşünün.

DOM ile olduğu gibi çalışmak istediğinizde getAttribute/ kullanın setAttribute(örn. Yalnızca düz metin). Farklı tarayıcılar ikisini karıştırır. Bkz olağandışı modları: özelliği, (in) uyumluluğu .


127
Bu cevap yeterince açık değil ... Bunu henüz anladığımı gerçekten hissetmiyorum.
temporary_user_name

1
@Aerovistae - bu konuda size katılıyorum. Açıkçası yeni bir cevap eklendi.
Olan

1
Ancak öğenin innerHTML'sini etkilemek istiyorsanız, setAttribute kullanmanız gerekir
Michael

3
HTML * :) demek
megawac

4
A.href tam url döndürür, ancak getAttribute ('href') tam olarak bu özniteliği (<a href = "/ help" ...) döndürür bulundu.
Plastik Tavşan

144

Gönderen JavaScript: Kesin Kılavuzu , bazı şeyleri açıklık getirmektedir. O belirtiyor HTMLElement tüm standart HTML tekabül ilişkilendirdiği JS özelliklerini tanımlamak HTML dokümanın nesneleri.

Bu nedenle, yalnızca setAttributestandart olmayan özellikler için kullanmanız gerekir .

Misal:

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

2
ve ayrıca, örneğinizdeki son setAttribute node.framebordertanımlı DEĞİLDİR sonra görünür , bu nedenle değeri geri almak için getAttribute almanız gerekir.
Michael

5
@Michael correct - bir değer ayarlamak için setAttribute kullanırsanız, onu almak için getAttribute kullanmanız gerekir.
olan

3
frameBorderDoğrudan ayarlamada yanlış bir şey yoktur , ancak büyük harf kullanımına dikkat edin. Birisi, HTML özelliklerinin JavaScript eşdeğerlerini deve haline getirmenin iyi bir fikir olduğunu düşündü. Bunun için herhangi bir şartname bulmayı başaramadım, ancak net 12 özel durumun (en azından HTML 4 için) olduğu konusunda hemfikir görünüyor. Aşağıdaki örneğe bakın: drupal.org/node/1420706#comment-6423420
aaaaaaaaaaaa

1
usemapNitelik Bir resim için dinamik harita oluştururken nokta gösterimi kullanılarak ayarlanamaz. Bu img.setAttribute('usemap', "#MapName");sizin cevabınızın bu usemapnedenle "standart dışı" olduğunu ima ediyor mu?
mseifert

1
Bu çoğunlukla yanlış. Bazı özniteliklerin tanımlanmış özellikleri vardır, bu nedenle yoktur. Gerçekten sadece özellikleri nasıl yazdıklarıyla ilgili. Özelliklerin standart olması ya da olmaması nedeniyle hiçbir şey yapmaz. Ancak, standart olmayan özelliklere yalnızca getAttribute () ile erişilebileceği doğrudur.
Ben

79

Önceki cevapların hiçbiri tam değildir ve çoğu yanlış bilgi içermektedir.

JavaScript'te bir DOM Öğesinin özelliklerine erişmenin üç yolu vardır . Her üçü de, onları nasıl kullanacağınızı anladığınız sürece modern tarayıcılarda güvenilir bir şekilde çalışır.

1. element.attributes

Elemanlar bir özellik var nitelikleri canlı getiriyi NamedNodeMap ait Attr itiraz ediyor. Bu koleksiyonun dizinleri tarayıcılar arasında farklı olabilir. Yani, sipariş garanti edilmez. NamedNodeMap( getNamedItemve setNamedItemsırasıyla) öznitelik ekleme ve kaldırma yöntemlerine sahiptir .

XML açıkça büyük / küçük harfe duyarlı olsa da, DOM özelliğinin dize adlarının normalleştirilmesini gerektirdiğini , bu nedenle iletilen adların getNamedItembüyük / küçük harfe duyarlı olmadığını unutmayın.

Örnek Kullanım:

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

Bu yöntemler Element, erişmeye attributesve yöntemlerine gerek duymadan doğrudan bulunur, ancak aynı işlevleri gerçekleştirir.

Yine, dize adının büyük / küçük harfe duyarlı olmadığını unutmayın.

Örnek Kullanım:

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 nesnesindeki özellikler; element.id

Birçok özelliğe DOM nesnesindeki uygun özellikler kullanılarak erişilebilir. Hangi niteliklerin mevcut olduğu, HTML'de hangi niteliklerin tanımlandığına değil, DOM düğümünün türüne bağlıdır. Özellikler, söz konusu DOM nesnesinin prototip zincirinde bir yerde tanımlanır. Tanımlanan belirli özellikler, erişmekte olduğunuz Öğe türüne bağlı olacaktır. Örneğin, classNameve idüzerinde tarif edildiği Elementve elemanlar (yani. Text ya da açıklama düğümleri) tüm DOM düğümlerinin biri. Ancak valuedaha dardır. HTMLInputElementDiğer öğeler üzerinde tanımlanmıştır ve olmayabilir.

JavaScript özelliklerinin büyük / küçük harfe duyarlı olduğuna dikkat edin. Çoğu özellik küçük harf kullanmasına rağmen, bazıları camelCase'dir. Emin olmak için her zaman özellikleri kontrol edin.

Bu "grafik", bu DOM nesneleri için prototip zincirinin bir bölümünü yakalar. Tamamlanmak için bile yakın değil, ancak genel yapıyı yakalar.

                      ____________Node___________
                      |               |         |
                   Element           Text   Comment
                   |     |
           HTMLElement   SVGElement
           |         |
HTMLInputElement   HTMLSpanElement

Örnek Kullanım:

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>

Dikkat: Bu, HTML spesifikasyonunun tanımladığı ve modern tarayıcıların nitelikleri nasıl ele aldığının bir açıklamasıdır. Eski, kırık tarayıcıların kısıtlamalarıyla uğraşmaya çalışmadım. Eski tarayıcıları desteklemeniz gerekiyorsa, bu bilgilere ek olarak, bu tarayıcılarda neyin kırıldığını da bilmeniz gerekir.


Netleştirdiğiniz için teşekkürler. Merak ediyorum, hangi IE sürümleri 'modern' olarak kabul edilir ve HTML özelliklerini takip eder?
jkdev

3
@jkdev IE asla modern olmaz. Yaşlanmak için ne gerekiyorsa.
Suraj Jain

Böyle ayrıntılı bir cevap için teşekkürler, DOM'dan ve HTMLElement'in Element'den miras alması gibi miras hakkında çok şey okudum, cevabınız mükemmel mantıklı.
Suraj Jain

16

setAttributeGerekli olduğu yerde bulduğum bir durum , karşılık gelen özellikler olmadığı için ARIA özniteliklerini değiştirirken. Örneğin

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

Böyle x.arialabelya da böyle bir şey yok , bu yüzden setAttribute kullanmanız gerekiyor.

Düzenleme: x ["aria-label"] çalışmıyor . Gerçekten setAttribute'a ihtiyacınız var.

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"

aslında Javascript'te bunu yapabilirsiniz x ["aria-label"]
Fareed Alnamrouti

@fareednamrouti Bu işe yaramıyor. Sadece test ettim. JS özellikleri html özniteliklerini etkilemez. Gerçekten setAttribute'a ihtiyacınız var.
Antimon

@Antimony Bu garip ama evet% 100 doğru oy kullanacağım
Fareed Alnamrouti

2
AriaLabel olmadığından emin misiniz?
jgmjgm

8

Bu cevaplar, özellikler ve nitelikler arasındaki büyük karışıklığa değinmiyor . Ayrıca, Javascript prototipine bağlı olarak, bazen bir özniteliklere erişmek için bir öğenin özelliğini kullanabilirsiniz ve bazen yapamazsınız.

İlk olarak, a'nın HTMLElementbir Javascript nesnesi olduğunu hatırlamanız gerekir . Tüm nesneler gibi özellikleri de vardır. Elbette, içinde neredeyse istediğiniz her şeyi denen bir özellik oluşturabilirsiniz HTMLElement, ancak DOM ile hiçbir şey yapması gerekmez (sayfada ne var). Nokta gösterimi ( .) özellikler içindir . Şimdi, özniteliklerle eşleştirilen bazı özel özellikler var ve o sırada veya yazarken sadece 4 tane garanti ediliyor (daha sonra daha fazla).

Tümü HTMLElementadlı bir özellik içerir attributes. DOM'daki öğelerle ilgili canlıHTMLElement.attributes bir Nesnedir. "Canlı", düğüm DOM'da değiştiğinde JavaScript tarafında değiştiğini veya tersi anlamına gelir. DOM öznitelikleri, bu durumda, söz konusu düğümlerdir. A , değiştirebileceğiniz bir özelliğe sahiptir. nesnelerin tüm düğümü değiştirebileceğiniz bir işlevi vardır . Düğüme doğrudan tuşla da erişebilirsiniz. Örneğin, diyebilirsiniz ile aynıdır (Side notu da geçebilir, böylece küçük harfe duyarlı değildir ); NamedNodeMapNode.nodeValueNamedNodeMapsetNamedItem.attributes["dir"].attributes.getNamedItem('dir');NamedNodeMap'DIR'

Doğrudan benzer bir işlevi var HTMLElementsadece çağrı nerede setAttributehangi otomatik olarak düğüm oluşturmak o var ve set değilse nodeValue. Ayrıca , gibi özel özellikler aracılığıyla doğrudan mülk olarak erişebileceğiniz bazı özellikler de vardır . İşte neye benzediğinin kaba bir haritası:HTMLElementdir

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 || ''

}

Böylece dirözellikleri 6 şekilde değiştirebilirsiniz :

  // 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';

Sen yöntemlerle # 1-5 ile tüm özellikleri güncelleştirmek, ama sadece olabilir dir, id, langve classNameyöntemle 6. ile.

HTMLElement'in uzantıları

HTMLElementbu 4 özel özelliğe sahiptir. Bazı öğeler HTMLElementdaha da eşlenmiş özelliklere sahip genişletilmiş sınıflardır . Örneğin, HTMLAnchorElementyer alır HTMLAnchorElement.href, HTMLAnchorElement.relve HTMLAnchorElement.target. Ama, dikkat sen (a olduğu gibi bu özel özellikleri yoktur unsurları bu özellikleri ayarlarsanız, HTMLTableElement) daha sonra özellikleri değiştirilmez ve onlar sadece normal özel özellikleridir. Daha iyi anlamak için, kalıtımının bir örneği:

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 || '' 
}

Özel Özellikler

Şimdi büyük uyarı: Tüm Javascript nesneleri gibi özel özellikler ekleyebilirsiniz. Ancak, bunlar DOM'daki hiçbir şeyi değiştirmeyecek. Yapabilirsin:

  const newElement = document.createElement('div');
  // THIS WILL NOT CHANGE THE ATTRIBUTE
  newElement.display = 'block';

Ama bu aynı

  newElement.myCustomDisplayAttribute = 'block';

Özel bir özellik ekleyerek bu araçlar ile bağlantılı olmayacaktır.attributes[attr].nodeValue .

Verim

Farkı göstermek için bir jsperf test çantası oluşturdum: https://jsperf.com/set-attribute-comparison . Temel olarak, sırayla:

  1. DOM'u etkilemediği ve nitelik olmadığı için özel özellikler .
  2. Tarayıcı tarafından sağlanan özel eşleştirmeleri ( dir, id, className).
  3. Nitelikler zaten varsa ,element.attributes.ATTRIBUTENAME.nodeValue =
  4. setAttribute ();
  5. Nitelikler zaten varsa ,element.attributes.getNamedItem(ATTRIBUTENAME).nodeValue = newValue
  6. element.attributes.ATTRIBUTENAME = newNode
  7. element.attributes.setNamedItem(ATTRIBUTENAME) = newNode

Sonuç (TL; DR)

  • Özel mülkiyet eşleştirmeleri kullanın HTMLElement: element.dir, element.id, element.className, veya element.lang.

  • Elemanın HTMLElementözel bir özellik ile genişletildiğinden% 100 eminseniz, bu özel eşlemeyi kullanın. (İle kontrol edebilirsiniz if (element instanceof HTMLAnchorElement)).

  • Özelliğin zaten var olduğundan% 100 eminseniz kullanın element.attributes.ATTRIBUTENAME.nodeValue = newValue.

  • Değilse kullanın setAttribute().


Şu dört özellik eşlemesinden bahsettiniz: dir, id, className ve lang. ClassList ne olacak? ClassList'in varolduğu garanti edilen bir özellik eşlemesi var mı?
Barzee

classList% 100 varolduğu garanti edilir, ancak bir dize özelliği değildir, canlı bir DOMTokenListnesnedir. .classNameDoğrudan ayarlamak manipüle etmekten daha hızlıdır classList, ancak her şeyin üzerine yazardınız.
Kısa Sigorta

<input> ve <textarea> etiketlerindeki .value değerine ne dersiniz? Ne tür onlar?
Daniel Williams

Cevapta belirtilenler W3C'nin "IDL özelliklerini yansıtan" olarak adlandırdığı şeydir. Değiştirdiğinizde .value, daha sonra özniteliklere yansıyan öğesinin değerini değiştirirsiniz HTMLInputElement. Ayrıca olmak zorunda da değiller string. dahili olarak.valueAsNumber değişir ve formu öznitelikte görünür . developer.mozilla.org/tr-TR/docs/Web/HTML/Attributesvalue stringvalue
ShortFuse

3

"JavaScript'te setAttribute vs .attribute = ne zaman kullanılır?"

Genel bir kural, .attributetarayıcıda çalışıp çalışmadığını kontrol etmektir.

..Tarayıcıda çalışıyorsa, gitmeye hazırsınız.

Öyle değil ..If kullanmak .setAttribute(attribute, value)yerine .attributeilişkin bu özelliğin.

Tüm özellikler için durulayın.

Eğer tembelseniz, sadece kullanabilirsiniz .setAttribute. Bu, çoğu tarayıcıda iyi çalışmalıdır. (Destekleyen tarayıcılar .attributeonu daha iyi optimize edebilir .setAttribute(attribute, value).)


0

Bu setAttribute'ı kullanmanın daha iyi olduğu bir durum gibi görünüyor:

Dev.Opera - Verimli 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);
}

2
Bu tomo7'yi paylaştığınız için teşekkürler, lütfen biraz daha açıklar mısınız? Does posElem.style = newStyle(Firefox'ta benim için çalıştı) tüm tarayıcılarda çalışmıyor? setAttributeBoyamadan kaçınılması tercih edilen performans nedenleriyle mi? O zaman posElem.style.cssText = newStyledaha fazla parfüm var mı posElem.style = newStyle?
Noitidart

0

öğedeki öznitelikleri (örneğin sınıf) ayarlama yöntemleri: 1. el.className = string 2. el.setAttribute ('sınıf', dize) 3. el.attributes.setNamedItem (nesne) 4. el.setAttributeNode (düğüm)

Basit bir kıyaslama testi yaptım ( burada )

ve setAttributeNode öğesinin setAttribute kullanmasından yaklaşık 3 kat daha hızlı olduğu anlaşılıyor.

performans bir sorunsa - "setAttributeNode" kullanın


Testi krom üzerinde yaptığınızı düşünüyorum. Chrome'umda, safari ve firefox kullanarak mac'umun üzerine eğlendim; beklenen 3 tanesi 3 farklı sonuç göstermiştir.
Olgun Kaya

0

Bununla ilgili Google API komut dosyasından ilginç yayın :

Bunu şöyle yaparlar:

var scriptElement = document.createElement("script");
scriptElement = setAttribute("src", "https://some.com");
scriptElement = setAttribute("nonce", "https://some.com");
scriptElement.async = "true";

setAttribute"Src" ve "nonce" için, ancak .async = ..."async" özelliği için nasıl kullandıklarına dikkat edin .

% 100 emin değilim, ama muhtemelen "async" yalnızca doğrudan .attr =atamayı destekleyen tarayıcılarda destekleniyor . Yani, bir şey yapmaya çalışmanın bir anlamı yok sestAttribute("async")çünkü tarayıcı .async=...anlamazsa "asenkron" özelliğini anlamayacaktır.

Umarım, devam etmekte olan "GAPI'yi küçült" araştırma projemden yararlı bir fikir . Yanlışsam düzelt.

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.