Updated @2017-08-06
公司前端同事閑聊,發現幾乎所有前端開發的同事都是有過后端背景的,究其原因是沒有學校會教授前端開發的知識,結果就是成長路徑靠各自摸索,一些基礎的知識很多前端都有所欠缺。相對更熟悉的《JavaScript權威指南》,這本《JavaScript高級程序設計》顯然更應該被希望進階的前端開發人員所閱讀。自己也是在越多過程中翻過來加深了一些基礎知識的理解。言歸正傳,這里補充一些對attributes的理解。
每個元素都有一個或多個attribute,這些attribute的用途是給出對應元素或者其內容的附加信息。
只有非自定義的attribute才會以property的形式被添加到DOM對象中,并通過DOM元素的property來訪問。
個人覺得可以這么理解:attributes的結構可以當做一個物理結構,就是實實在在的存在于DOM樹上的內容,可視;而properties則是數值化的DOM。所有針對attributes的改動,不一定能同步到properties,因為必須符合一一定的標準。
一個舉例是,火箭燃料中填充了100L(attributes),刻度盤數據上也會增大100L,反之只是在火箭的冰箱中塞幾瓶可口可樂,并給可樂取名為"燃料附加",顯然是不會真的導致刻度盤上的火箭燃料數值增大的。
attribute和property并非一定能對應上,比如獲取一個DOM的class可以通過,dom.getAttribute("class")
和 dom.classList.value
;比如獲取一個DOM的style可以通過 dom.getAttribute("style")
和dom.style
,其中前者得到的結果為字符串,后者得到的結果為一個對象;比如設置DOM的style卻僅可以通過dom.setAttribute("style", "font-size:12px;color:red;");
來使樣式設置生效。
曾經在面試中被問到了attr()和prop()的區別,稍加學習記錄如下
1. attribute和property
attribute
一個網頁就是一棵DOM樹,DOM樹由節點構成,節點分為三種:元素節點、文本節點、屬性節點。所有的屬性節點構成了一個屬性的數組,我們以如下HTML代碼為例:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>attr() vs prop()</title>
</head>
<body>
<input type="text" value="Name:">
<input type="checkbox" checked="false">
<script src="http://ajax.googleapis.com/ajax/libs/jquery/1.11.2/jquery.min.js"></script>
</body>
</html>
我們在瀏覽器窗口的console中輸出:
var inputs = document.getElementsByTagName('input')
var input = inputs[0];
input.attributes
得到的結果是:
NamedNodeMap {0: type, 1: value, length: 2, getNamedItem: function, setNamedItem: function, removeNamedItem: function, item: function…}
可以看到,這個節點對象里面有很多的屬性,我們只設置了兩個,其他的是繼承自原型鏈上的。
property
所有節點都是對象,對象上的屬性叫做property,我們可以簡單通過遍歷這個對象來查看他的properties,如下為在瀏覽器中執行的例子:
var input = inputs[0];
for(var key in input) {console.log(key);}
如下為輸出的結果:
VM445:2 webkitEntries
VM445:2 incremental
VM445:2 webkitdirectory
VM445:2 selectionDirection
VM445:2 selectionEnd
VM445:2 selectionStart
VM445:2 labels
VM445:2 validationMessage
...
因為property輸出太多了所以沒有全部列出,但自己執行后仔細查找會發現,type和value兩個屬性也存在于properties中。
2. property和attribute使用上有什么區別?
通過上節我們看到prop來自節點對象自帶的,它包含了很多property;而attr來自對象的attributes,是我們在元素節點上添加屬性節點才會有的。
對于上例的文本框,我們可以通過property方式像這樣input.value
或者 attribute方式像這樣 input.getAttribute( "value" )
來獲得值,并且得到的結果都是 "Name:"。
當我們在頁面中編輯文本框的值,再次在console中獲取的時候發現input.value
的值是更新后的值,而input.getAttribute
的值仍舊是舊的。
因此差別就是: property記錄的值會按照用戶操作實時更新,而attribute記錄的都是初始值。
3. prop()和attr()的區別?
根據 W3C forms specification, checked 屬性是一個 boolean attribute, 因此checked property只能是true或者false(當勾選為true,未勾選或者未設置為false):
- elem.checked // true (Boolean) 會隨著勾選狀態而改變
jQuery的prop()方法是和上面直接取property一樣 ,因此:
- $( elem ).prop( "checked” ) //true (Boolean) 會隨著勾選狀態而改變
而拿attribute拿到的只是初始的值:
- elem.getAttribute( "checked" ) // "checked" (String) 記錄初始狀態, 值為"checked"或者任意你設置的值,不會隨著勾選狀態而改變
jQuery的attr()方法獲的的結果也跟getAttribute是一致的:
- $('input[type="checkbox"]').attr( 'checked' ) // 同上一條
至于說jQuery的歷史版本中,attr()的實現曾經會跟getAttribute不一致,比如返回結果是會隨著勾選狀態變化的字符串,或者返回結果是Boolean類型的值,知道即可因為現在的用法是一致的了~
參考來源: JavaScriptDom編程藝術, stackoverflow, jQuery API, JavaScript高級程序設計