1. 程式人生 > >區分元素特性attribute和物件屬性property

區分元素特性attribute和物件屬性property

前面的話

  其實attribute和property兩個單詞,翻譯出來都是屬性,但是《javascript高階程式設計》將它們翻譯為特性和屬性,以示區分。本文將詳細介紹特性和屬性的不同之處

定義

  元素特性attribute是指HTML元素標籤的特性

  下面的id、class、title、a都是特性,其中a叫做自定義特性

<div id="id1" class="class1" title="title1" a='a1'></div>

  物件屬性property是指元素節點的屬性

  下面的id、title、b都是屬性,其中b叫做自定義屬性

<div id="test"></div>
<script>
test.id = 'id2';
test.title = 'title2';
test.b = 'b2';
</script>

共有

  id、title等既是屬性,也是特性。修改屬性,其對應的特性會發生改變;修改特性,屬性也會改變

  【1】修改元素特性(以title為例)

<div id="test" title='123'>測試內容</div>
<script>
console.log(test.title);
//123 document.onclick = function(){ test.setAttribute('title','456'); console.log(test.title);//456 } </script>

  【2】修改物件屬性

<div id="test" title='123'>測試內容</div>
<script>
console.log(test.getAttribute('title'));//123
document.onclick = function(){
    test.title 
= '456'; console.log(test.getAttribute('title'));//456 } </script>

例外

  class和for這兩個元素特性是例外,因為class和for是保留字,無法直接在物件屬性中使用。所以在物件屬性中,class變成了className,而for變成了htmlFor

  【1】class

<div id="test" class="class1">測試內容</div>
<script>
console.log(test.getAttribute('class'));//'class1'
console.log(test.className);//'class1'
console.log(test.class);//undefined
</script>

  【2】for

<label id="test" for="input"></label>
<script>
console.log(test.getAttribute('for'));//'input'
console.log(test.htmlFor);//'input'
console.log(test.for);//undefined
</script>

特殊

  style和onclick是兩個特殊的特性,它們雖然有對應的屬性名,但屬性值與通過getAttribute()返回的值並不相同

  【1】style

  通過getAttribute()訪問時,返回的style特性值中包含的是CSS文字,而通過屬性來訪問它則會返回一個CSSStyleDeclaration物件

<div id="test" style="height: 100px;width: 100px;"></div>
<script>
console.log(test.getAttribute('style'));//'height: 100px;width: 100px;'
//{0: "height", 1: "width", alignContent: "", alignItems: "", alignSelf: ""…}
console.log(test.style);
console.log(typeof test.style);//'object'
console.log(test.style.height);//'100px'
</script>

  【2】onclick

  如果通過getAttribute()訪問,會返回相應程式碼的字串。而訪問onclick屬性時,會返回一個javascript函式

  [注意]其他事件處理程式也類似

<div id="test" onclick = "alert(1)">測試內容</div>
<script>    
console.log(test.getAttribute('onclick'));//'alert(1)'
console.log(test.onclick);//'function onclick(event) {alert(1)}'
console.log(typeof test.onclick);//'function'
</script>

  [注意]如果通過物件屬性設定onclick屬性,則不會有對應的元素特性

<div id="test">測試內容</div>
<script>
test.onclick = function(){
    alert(1);
}    
console.log(test.getAttribute('onclick'));//null
console.log(test.onclick);//'function onclick(event) {alert(1)}'
console.log(typeof test.onclick);//'function'
</script>

自定義

  【1】自定義特性

  自定義特性用來在HTML元素上繫結一些額外的資訊。但是自定義特性無法在物件屬性中有所體現

<div id="test" index='1'></div>
<script>
console.log(test.getAttribute('index'));//'1'
console.log(test.index);//undefined    
</script>

  HTML5新增了資料集屬性dataset(規範的自定義特性),用於儲存頁面或應用程式的私有定製資料。資料集屬性以'data-'為字首,可以使用javascript中物件屬性dataset訪問data-*的值

  由於元素特性的值以'-'做間隔,在物件屬性中將轉換為首字母大寫的形式

data-index-one -> dataset.indexOne

  所以,元素特性的值一定不要出現大寫,否則物件屬性會解釋出錯

  [注意]IE10-瀏覽器不支援dataset

<div id="test" data-index-one="1"></div>
<script>
console.log(test.getAttribute('data-index-one'));//'1'
console.log(test['data-index-one']);//undefined
console.log(test.dataset.indexOne);//'1'
</script>

【相容程式碼】

function getDataSet(element){
    if(element.dataset){
        return element.dataset;
    }
    var attrs= element.attributes;
    var len = attrs.length;
    var data = {};
    for(var i=0;i<len;i++){
        var sName = attrs[i].name;
        var sValue = attrs[i].value;
        if(sName.substring(0,5)==="data-"){
            var tempName = sName.slice(5).replace(/-([A-Za-z])/g,function(item,item1){
                return item1.toUpperCase();
            });
            data[tempName] = sValue;
        }   
    }
    return data;
}
var dataset = getDataSet(box);

  【2】自定義屬性

  自定義屬性在javascript中非常常用,是一種常用的程式設計技術。但元素特性上並不會有所體現

<div id="test"></div>
<script>
test.index = 1;
console.log(test.index);//1
console.log(test.getAttribute('index'));//null
</script>

  [注意]可以使用資料集屬性的逆向操作來實現自定義屬性向元素特性的對應 

<div id="test"></div>
<script>
test.dataset.index = 1;
console.log(test.getAttribute('data-index'));//1
</script>

混淆

  IE7-瀏覽器下會混淆元素特性attribute和物件屬性property。在下列情況下,IE7-瀏覽器通過getAttribute()返回的值與物件屬性相同

  【1】class

  設定物件屬性className,在IE7-瀏覽器下,訪問元素特性時,引數也設定為className才有效

  [注意]for也有類似效果,不再贅述

<div id="test"></div>
<script>
test.className = 'class1';
//IE7-瀏覽器返回'class1',其他瀏覽器返回null
console.log(test.getAttribute('className'));

//IE7-瀏覽器返回null,其他瀏覽器返回'class1'
console.log(test.getAttribute('class'));
</script>

  【2】style

  IE7-瀏覽器通過getAttribute()方法返回的元素特性與物件屬性一樣,都是CSSStyleDeclaration物件

  [注意]click等事件處理程式也有類似效果,不再贅述

<div id="test" style="width: 100px;"></div>
<script>
//IE7-瀏覽器下,返回CSSStyleDeclaration物件;其他瀏覽器返回'width: 100px;'
console.log(test.getAttribute('style'));
//IE7-瀏覽器下,返回true;其他瀏覽器返回false
console.log(test.getAttribute('style') === test.style);
</script>

  【3】自定義

  在IE8-瀏覽器下,自定義特性會自動對應為物件屬性,自定義屬性也會自動對應為元素特性

<div id="test" a='a1'></div>
<script>
test.b = 'b1';
//IE7-瀏覽器返回'a1',其他瀏覽器返回undefined
console.log(test.a);
//IE7-瀏覽器返回'b1',其他瀏覽器返回null
console.log(test.getAttribute('b'));
</script>

總結

  物件節點對於HTML標籤元素說來,是元素DOM化的結果。與此相對應,物件屬性也是元素特性的DOM化結果

  由於javascript中保留字的限制,存在class和for這兩種例外情況

  與普通的元素特性不同,通過style實現的指令碼化CSS機制和通過onclick等實現的事件處理機制是DOM的兩大功能,它們被DOM實現為物件,而不僅僅是普通的字串

  自定義特性和自定義屬性非常有用,但卻沒有對應關係。HTML5新增的資料集屬性dataset建立了兩者的聯絡

  最後,IE7-瀏覽器對元素特性和物件屬性有所混淆。如果網站仍然需要相容IE7-瀏覽器,就要非常小心

  歡迎交流