javascript 特性(attribute)与属性(property)

特性和属性是javascript中两个很重要同时也很容易混淆的概念:

特性(attribute) 是DOM构建的一个组成部分

属性(property) 是元素保持运行时信息的主要手段,并且可以通过属性获取这些运行时信息

我们可以通过一个简单的示例来演示特性与属性的区别:

<html>
    <head></head>
    <body>
        <a id="link" href="./1.html">link</a>
        <script>
            var link = document.getElementById('link');
            var newHref = "./2.html";
            link.href = newHref;
            console.log(link.href===newHref,link.getAttribute('href')===newHref);
            // false true
            console.log("attribute:",link.getAttribute('href'));
            // attribute: ./2.html
            console.log("property:",link.href);
            // property: file:///C:/Users/Administrator/Desktop/jquery/2.html
        </script>
    </body>
</html>

在上述代码中,我们创建了一个链接标签,获取它的引用,并将它的href属性修改为一个新值。通过console日志我们可以看到不管是特性还是属性都已经被成功修改,但是特性与属性的值却是不一样的。特性的值是我们赋予的,而属性值则由相对路径被转成了绝对路径。回忆前文关于属性的定义,属性是元素保持运行时信息的主要手段。这里已经能看出属性和特性的一个区别。

1 DOM 特性和 DOM 属性

在访问或设置元素的特性值时有两种方法:使用传统的 DOM 方法 getAttributesetAttribute 或使用 DOM 对象上与之对应的属性。

举例来说,假设一个元素保存在对象e中,如果我们希望获取元素的id属性,可以通过下面两种方式:

e.getAttribute('id');
e.id;

同样,不管我们通过下面的哪种方式,都可以修改元素的id值:

e.setAttribute('id','test');
e.id = 'test';

也就是说,设置了特性的值,属性值会跟着改变,反之亦然。

但是这并不代表特性和属性共享一个相同的值。特性和对应的属性虽然有联系,但并不总是相同的。

1.1 跨浏览器命名

在谈到特性和对应的属性命名时,属性的名称在不同的浏览器上通常更加一致。如果在一个浏览器中,我们能通过一个特定的名称访问一个属性,那么在其他浏览器中,很有可能也可以用同样的名称访问该属性。属性命名之间虽然会有一些差异,但是特性和属性命名之间的差异则会更多。

举个例子,在大多数浏览器中都可以用class获取到元素的class特性,但是IE中却需要使用className,并且IE对应的属性名称也是className。

1.2 命名限制

特性(attribute),表示为传递给 DOM 方法的字符串,其命名规范是非常自由的。但属性名称,由于可以作为标识符使用点表示法进行访问,所以其命名规范是更受限的,属性名称必须符合标识符的规则,而且还有一些保留关键字也不能用。

例如,<label>的for特性是关键字,所以在ECMAScript规范中,可以用htmlFor属性进行表示,同样的class由className来表示。另外,由多个单词组成的特性名称由“驼峰式”的属性名称来表示,例如,特性readonly的属性名称为readOnly。更多差异,参见下表。

特性名称(Attribute) 属性名称 (Property)
for htmlFor
class className
readonly readOnly
maxlength className
class className
cellspacing cellSpacing
rowspan rowSpan
colspan colSpan
tabindex tabIndex
cellpadding cellPadding
usemap useMap
frameborder frameBorder
contenteditable contentEditable

1.3 自定义特性的行为

并不是所有的特性都有元素的属性来表示。虽然这适用于 HTML DOM 的原生特性,但我们在页面元素上定义的自定义特性(custom attributes),则不会自动转换为元素属性的表达方式。要想访问这些元素的特性值,需要使用 DOM 方法 getAttribute() 和 setAttribute() 。

如果不确定一个特性的属性是否存在,可以对其进行测试,如果不存在的话再使用 DOM 方面,参见下面的例子:

let value = element.someValue?element.someValue:
                              element.getAttribute('someValue');

在 HTML5 中,对所有的自定义特性使用 data- 前缀,以便遵守 HTML5 的规范。即便使用的是 HTML4,也同样建议使用这种方式,以便将标签适应未来。除此之外,这是分离自定义特性和原生特性一个很好的约定。

1.4 性能注意事项

总的来说,属性的访问速度比相应的特性访问速度要快,特别是在IE浏览器中。让我们来证明一下。

<html>
    <head></head>
    <body>
        <div id="test"></div>
        <script>
            var count = 5000000;
            var element = document.getElementById('test');
            var begin ,end, value,n;

            begin = new Date();
            for(n=0;n<count;n++){
                value = element.getAttribute('id');
            }
            end = new Date();
            console.log("getAttribue cost "+(end.getTime()-begin.getTime())+" ms.");

            begin = new Date();
            for(n=0;n<count;n++){
                value = element.id;
            }
            end = new Date();
            console.log("element.id cost "+(end.getTime()-begin.getTime())+" ms.");

            begin = new Date();
            for(n=0;n<count;n++){
                element.setAttribute('id','test');
            }
            end = new Date();
            console.log("setAttribue cost "+(end.getTime()-begin.getTime())+" ms.");

            begin = new Date();
            for(n=0;n<count;n++){
                element.id = 'test';
            }
            end = new Date();
            console.log("write element.id cost "+(end.getTime()-begin.getTime())+" ms.");
        </script>
    </body>
</html>

下面是不同浏览器的运行结果(单位为ms):

浏览器 getAttribute Property获取 setAttribue Property设置
chrome 71.0.3578.98 288 96 1715 669
Firefox 64.0 13 12 746 439
Edge 17.17134 3018 2301 48125 1691
IE 11 33676 16386 40683 15775

可以看出来通过属性设置或者获取值的性能明显优于通过 DOM 方式, IE在这方面的表现尤为突出。

猜你喜欢

转载自blog.csdn.net/qiumingsheng/article/details/85108876
今日推荐