คำตอบเหล่านี้ไม่ได้จริงๆที่อยู่ความสับสนระหว่างขนาดใหญ่ที่มีคุณสมบัติและคุณลักษณะ นอกจากนี้ขึ้นอยู่กับต้นแบบ Javascript บางครั้งคุณสามารถใช้คุณสมบัติขององค์ประกอบเพื่อเข้าถึงแอตทริบิวต์และบางครั้งคุณไม่สามารถทำได้
ก่อนอื่นคุณต้องจำไว้ว่าHTMLElement
เป็นวัตถุ Javascript เช่นเดียวกับวัตถุทั้งหมดพวกมันมีคุณสมบัติ แน่นอนว่าคุณสามารถสร้างสถานที่ที่เรียกว่าเกือบทุกอย่างที่คุณต้องการภายในHTMLElement
แต่ไม่ต้องทำอะไรกับ DOM (มีอะไรในหน้า) สัญกรณ์จุด ( .
) สำหรับคุณสมบัติ ตอนนี้มีคุณสมบัติพิเศษบางอย่างที่ถูกแมปกับแอตทริบิวต์และในเวลาหรือการเขียนมีเพียง 4 ที่รับประกัน (เพิ่มเติมในภายหลัง)
ทั้งหมดHTMLElement
s attributes
รวมถึงคุณสมบัติที่เรียกว่า HTMLElement.attributes
เป็นวัตถุถ่ายทอดสด NamedNodeMap
ที่เกี่ยวข้องกับองค์ประกอบใน DOM "สด" หมายความว่าเมื่อโหนดเปลี่ยนใน DOM พวกเขาเปลี่ยนในด้าน JavaScript และในทางกลับกัน แอตทริบิวต์ DOM ในกรณีนี้คือโหนดที่เป็นปัญหา A Node
มี.nodeValue
คุณสมบัติที่คุณสามารถเปลี่ยนได้ NamedNodeMap
วัตถุมีฟังก์ชั่นที่เรียกว่าsetNamedItem
ที่คุณสามารถเปลี่ยนโหนดทั้งหมด คุณสามารถเข้าถึงโหนดได้โดยตรงโดยใช้กุญแจ ตัวอย่างเช่นคุณสามารถพูดได้ว่า.attributes["dir"]
สิ่งใดที่เหมือนกัน.attributes.getNamedItem('dir');
(หมายเหตุด้านข้างNamedNodeMap
ไม่ตรงตามตัวพิมพ์ใหญ่ - เล็กดังนั้นคุณสามารถผ่านได้'DIR'
)
มีฟังก์ชั่นที่คล้ายกันโดยตรงใน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 || ''
}
ดังนั้นคุณสามารถเปลี่ยน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 แต่เพียงdir
, id
, lang
และclassName
ด้วยวิธีการ # 6
ส่วนขยายของ HTMLElement
HTMLElement
มีคุณสมบัติพิเศษทั้งสี่ องค์ประกอบบางอย่างเป็นคลาสที่ขยายของ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 โดยทั่วไปในการสั่งซื้อ:
- คุณสมบัติแบบกำหนดเองเพราะพวกเขาไม่ส่งผลกระทบต่อ DOM และมีไม่แอตทริบิวต์
- แมปพิเศษให้โดยเบราว์เซอร์ (
dir
, id
, className
)
- หากคุณลักษณะที่มีอยู่แล้ว ,
element.attributes.ATTRIBUTENAME.nodeValue =
- setAttribute ();
- หากคุณลักษณะที่มีอยู่แล้ว ,
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
หากคุณมั่นใจ 100% องค์ประกอบนั้นเป็นส่วนขยายที่HTMLElement
มีคุณสมบัติพิเศษให้ใช้การจับคู่พิเศษนั้น (คุณสามารถตรวจสอบได้if (element instanceof HTMLAnchorElement)
)
หากคุณเป็น 100% element.attributes.ATTRIBUTENAME.nodeValue = newValue
ว่าแอตทริบิวต์ที่มีอยู่แล้วการใช้งาน
setAttribute()
ถ้าไม่ได้ใช้
.setAttribute()
เป็น[key] = value
ทุกอย่างก็เริ่มทำงานได้อย่างน่าอัศจรรย์