# attribute v.s. property
Attributes – is what’s written in HTML.
Properties – is what’s in DOM objects.
### DOM(Document Object Model)
在DOM的標準下,一份文件中所有的標籤定義,包括文字,都是object,這些物件以文件定義的結構,形成了一個樹狀結構。

DOM tree 包含 4 種節點 (parentNode,childNodes)
* 文件節點 (Document node):整個文件
* 元件節點(Element node): html, head, body, ul, li…
* 屬性節點(Attribute node): id, class, type…
* 文本節點(text node): h1, p, span…
### HTML attributes
1. **attributes 由 HTML 定義,所有出現在 HTML 標籤內的描述皆為 attributes(standard attributes)**
```+
<div id="root" class="hello">
<!-- id, class 為 div 的 attributes -->
<img src="https://i.imgur.com/AK2FguR.jpeg" alt="圖片">
<!-- src, alt 為 img 的 attributes -->
</div>
```
[W3SCHOOL: img的標準 attributes](https://www.w3schools.com/tags/tag_img.asp)
2. **操作 HTML attributes**
elem.hasAttribute(name) — 檢查是否有該 attribute。
elem.getAttribute(name) — 存取該 attribute。
elem.setAttribute(name, value) — 新增 attribute。
elem.removeAttribute(name) — 移除該 attribute。
elem.attributes —存取所有 attributes。
3. **所有的 attributes type 皆為 string**
4. **Their name is case-insensitive (id is same as ID). 對大小寫不敏感**
```+
<body>
<div id="elem" about="Elephant"></div>
<script>
alert( elem.getAttribute('About') ); // (1) 'Elephant', reading
elem.setAttribute('Test', 123); // (2) writing
for (let attr of elem.attributes) { // (3) list all
alert( `${attr.name} = ${attr.value}` );
}
</script>
</body>
```
### DOM properties
property屬於DOM物件,當瀏覽器加載頁面時,它解析HTML並從中生成DOM物件。
DOM實質就是javascript中的物件,因此存取 DOM properties 的方法就和存取 JavaScript 中的 object 一樣。
1. **大多數標準的HTML 特性(attributes)會自動變成DOM對象的屬性(properties)**。例如,如果標籤是
`<body id="page"> <--> body.id="page"`
3. **非標準的(自定義的) HTML attributes 並不會產生相對應的 DOM properties**
```+
<div id="test" class="button" foo="1"></div>
<script>
console.log(document.querySelector('#test').id); // return string: "test"
console.log(document.querySelector('#test').className); // return string: "button"
console.log(document.querySelector('#test').foo); // return undefined
</script>
```
3. **DOM properties 的 type 不一定是 string**
[1]boolean
* input.checked的property是回傳boolean值,而使用getAttribute則會回傳空字串。
```+
<input id = "input" type = "checkbox" checked>Check Box
<script>
console.log(input.getAttribute('checked')); //empty string
console.log(input.checked); //true
</script>
```
[2]style
* The style attribute is a string, but the style property is an object
```+
<div id="div" style="color:red;font-size:120%">Hello</div>
<script>
// string
alert(div.getAttribute('style')); // color:red;font-size:120%
// object
alert(div.style); // [object CSSStyleDeclaration]
</script>
```
[3] href
* Quite rarely, even if a DOM property type is a string, it may differ from the attribute.
* the href DOM property is always a full URL
```+
<a id="a" href="#hello">link</a>
<script>
// attribute
alert(a.getAttribute('href')); // #hello
// property
alert(a.href ); // full URL
</script>
```
4. **DOM 物件的property 改變的時候通常對應的attribute 也會改變,但有例外=>input.value**
```+
<input>
<script>
let input = document.querySelector('input');
// attribute => property
input.setAttribute('id', 'id');
alert(input.id); // id (updated)
// property => attribute
input.id = 'newId';
alert(input.getAttribute('id')); // newId (updated)
</script>
```
```+
<input>
<script>
let input = document.querySelector('input');
// attribute => property
input.setAttribute('value', 'text');
alert(input.value); // text
// NOT property => attribute
input.value = 'newValue';
alert(input.getAttribute('value')); // text (not updated!)
</script>
```
* Changing the attribute value updates the property.
* But the property change does not affect the attribute.
5. **如果標籤上沒有設置attribute,使用getAttribute()指定該屬性會取得null,DOM物件的property會給予預設值undefined。**
```+
<input>
<script>
console.log(document.querySelector("input").getAttribute("ph")) // null
console.log(document.querySelector("input").ph); //undefined
</script>
```
### 結論
* Attributes – is what’s written in HTML.
* Properties – is what’s in DOM objects.
| | Properties | Attributes |
| -------- | -------- | -------- |
| Type | 任何值,標準的屬性具有規範中描述的類型 | string |
| Name | 對大小寫敏感的 | 對大小寫不敏感的 |
> 在大多數情況下,**建議使用DOM Properties**。僅當DOM Properties無法滿足開發需求,並且我們真的需要Attributes 時才使用,例如:
>
* 我們想要讀取HTML中“original” value的時候,但對應的DOM Properties可能不同: href property 永遠是完整的url型式
* 用戶操作行為可能會導致value改變,在這之後,如果我們想從 HTML 中恢復“original” value,它仍然在attribute中
### 參考資料
[Attributes and properties](https://javascript.info/dom-attributes-and-properties#property-attribute-synchronization)
https://jimmyswebnote.com/html-attributes-and-dom-properties/
https://openhome.cc/Gossip/JavaScript/W3CDOM.html