在大多數的文章中,attribute 通常被翻譯爲「特性」,property 被譯爲「屬性」。html
把結論寫在最前面,若是你全都懂,後面就不用看了。java
HTML attribute | DOM property |
---|---|
值永遠是字符串或 null |
值能夠是任意合法 js 類型 |
大小寫不敏感 | 大小寫敏感 |
不存在時返回 null |
不存在時返回 undefined |
對於 href , 返回 html 設置的值 |
對於 href 返回解析後的完整 url |
更新 value , 屬性也更新 |
更新 value , 特性不更新 |
當咱們書寫 HTML 代碼的時候,咱們爲 HTML <abbr title="Element">元素</abbr>設置<abbr title="attribute">特性</abbr> ,例如:git
<input id="name" value="justjavac" />
咱們寫了一個 input
標籤,並給他定義了 2 個<abbr title="attribute">特性</abbr> (id
和 value
)。當瀏覽器解析這段代碼的時候,會把 html 源碼解析爲 DOM 對象,確切的說是解析爲 HTMLInputElement
對象。HTMLInputElement
的繼承關係是:github
HTMLInputElement ↓ HTMLElement ↓ Element ↓ Node ↓ EventTarget ↓ Object
經過查看文檔會發現,HTMLInputElement
的原型上定義了不少<abbr title="property">屬性</abbr>和方法,例如 form
, name
, type
, alt
, checked
, src
, value
等等,還有從 HTMLElement
繼承來的 id
, title
, clientTop
等等。瀏覽器
若是仔細找找,就不難發現其中就有咱們爲 input
標籤訂義的<abbr title="attribute">特性</abbr>:id
和 value
。當瀏覽器解析網頁時,將 HTML <abbr title="attribute">特性</abbr>映射爲了 DOM <abbr title="property">屬性</abbr>。dom
而 Element
類還有一個 attributes
屬性,裏面包含了全部的特性。url
可是,HTML attribute 和 DOM property 並不老是一對一的關係。prototype
當瀏覽器解析完 HTML 後,生成的 DOM 是一個繼承自 Object 的常規 JavaScript 對象,所以咱們能夠像操做任何 JS 對象那樣來操做 DOM 對象。翻譯
const el = document.getElementById('name') el.foo = 'bar' el.user = { name: 'jjc', age: '18'}
也能夠爲其添加方法。若是你想給每一個 html 元素都添加屬性或方法,甚至能夠直接修改 Element.prototype
,不過咱們不推薦這麼作。code
和 DOM 屬性相似,除了那些規範裏定義的標準特性外,HTML 也能夠添加非標準的屬性,例如:
<input id="name" value="justjavac" foo="bar" />
當 HTML 特性映射爲 DOM 屬性時,只映射標準屬性,訪問非標準屬性將獲得 undefined
。
const el = document.getElementById('name') el.foo === undefined
好在 DOM 對象也提供了操做特性的 API:
Element.hasAttribute(name)
– 判斷某個特性是否存在elem.getAttribute(name
) – 獲取指定特性的值elem.setAttribute(name, value)
– 設置指定特性的值elem.removeAttribute(name)
– 移除指定特性以上 API 定義在 Element
上。
根據 HTML 規範,標籤以及特性名是不區分大小寫的,所以如下代碼是同樣的:
el.getAttribute('id') el.getAttribute('ID') el.getAttribute('iD')
而且,特性永遠都是字符串或 null
。若是咱們爲特性設置非字符串的值,則引擎會將此值轉換爲字符串。屬性是具備類型的:
el.getAttribute('checked') === '' // 特性是字符串 el.checked === false // 屬性是 boolean 類型的值 el.getAttribute('style') === 'color:blue' // 特性是字符串 typeof el.style === 'object' // 屬性是 CSSStyleDeclaration 對象
即便都是字符串,屬性和特性也可能不一樣,有一個例外就是 href
:
el.getAttribute('href') === '#tag' // 特性原樣返回 html 設置的值 el.href === 'http://jjc.fun#tag' // 屬性返回解析後的完整 uri
當標準的特性更新時,對應的屬性也會更新;反之亦然。
可是 input.value
的同步是單向的,只是 attribute --> property
。當修改特性時,屬性也會更新;可是修改屬性後,特性卻仍是原值。
el.setAttribute('value', 'jjc'); // 修改特性 el.value === 'jjc' // 屬性也更新了 el.value = 'newValue'; // 修改屬性 el.getAttribute('value')) === 'jjc' // 特性沒有更新
非標準 HTML 特性並不會自動映射爲 DOM 屬性。當咱們使用 data-
開頭的特性時,會映射到 DOM 的 dataset 屬性。中劃線格式會變成駝峯格式:
el.setAttribute('data-my-name', 'jjc'); el.dataset.myName === 'jjc' el.setAttribute('data-my-AGE', 18); el.dataset.myAge === '18'
HTML 容許咱們自定義標籤,也能夠擴展標籤的特性,可是咱們推薦使用已經進入 HTML5 規範的自定義特性 data-*
。好比咱們想爲 div
標籤增長一個 age
特性,咱們能夠有 2 種選擇:
<div age="18">justjavac</div> <div data-age="18">justjavac</div>
雖然第一種代碼更短,可是卻有一個潛在的風險。由於 HTML 規範是一直髮展變化的,也許在將來的某個版本中,age
被添加進了標準特性裏面,這將會引發潛在的 bug。
閱讀原文: HTML attribute 和 DOM property討論地址:#15
若是你想參與討論,請點擊這裏