DOM系列:Attribute和Property

发布于 大漠

这两天一直在看DOM元素的attributeproperty,简单让人晕。从直译上,我一开始都理解为“属性”,而且对于我这样的新手,将两者混淆在一起,傻傻的分不清楚。后来经过大大们的指点,知道两者是不同的东西,但两者之间又有紧密的联系。为了能更清晰的整明白两者的关系与不同,所以把自己理解和搜集的资料理了一下,希望对新手有所帮助。

Attribute和property形象上的描述

文章开头也说了,自己对attributeproperty两者理不清楚,在搜集两者差异的时候,看到了Web技术研究所站长对两者的描述,简值是绝了,让初学者一看就易于理解,下面这部分内容直接复制过来了。

attributeproperty都被翻译成“属性”,但是它们有着本质上的区别。拿生活中的示例来说,或许对于像我这样的新手更易于理解。

“桌子上有个苹果”。attribute仅仅是描述了这个“有苹果”的事实,而property则是直指那个桌子上的苹果。这里的苹果是一个实体,用attribute来描述只能说明这个事件的事实。它无法准确的描述出具体哪个苹果在桌子上。再举个示例 —— “我爸是李刚”。attribute仅仅是描述了“李刚”这个名字,而property则是直接代表“李刚”这个人(一个实体)。叫“李刚”这个名字的人很多,所以attribute无法确切表示。而property则是直指实体的,可以准确描述事物。但也不是说attribute就绝对无法准确表示事物,只是attribute只能用文字描述,所以它要精确描述一个东西的代价是比property高了许多。比如描述“李刚”可以用他的身份证号码之类的,可是说不定人家的身份证还是伪造的,所以还需要更多的文字描述才能准确的说明一个东西。

那么既然propertyattribute好,为什么还需要attribute呢?就说“我爸是李刚”这件事吧,过了这么多年了也许很多人都忘了。property是保存在记忆(比如计算机的内存memory)中的,虽然一开始很准确,但是无法长期保存。我们经常会把需要长期保存的东西用文字描述下来,这时就需要用到attribute。而且attributeproperty并不冲突,我们经常会翻阅一些旧资料来补充我们渐淡的记忆。

这些就是它们本质上的区别,在程序中我们可以用另外的方式说明它。attribute是标记语言的概念(比如HTML语言),而标记语言本身就是一种文本,所以attribute这种文本描述的性质在标记语言中很容易使用。而property则是保存在内存中,而内存会随着程序运行结束被释放,因此变得无法长期储存。在JavaScript中,DOM对象通常都是多重继承的。同时继承了HTML和JavaScript的ObjectObject是完完全全的内存对象,所以使用的是property,而HTML本身就是标记语言,所以使用的是attribute。当这两个东西被继承到同一个对象上的时候经常会让人混淆起来。由于一些attribute是很常用的,比如idclass等,所以DOM把它们映射到property上以方便使用。这样我们就会遇到一个对象同时具有id这个attributeproperty(由于class是保留字,所以它被映射到property上时变成className)。

虽然被DOM这样一搞,初学者易于混淆attributeproperty。但上面的比喻,估计有帮助初学者易于理解。但要更清晰的理解,还是有必要通过示例来阐述。接下来,我们回到我们的代码世界当中。

attribute和property的定义

其实上面的示例描述,对attributeproperty已经定义的非常清晰。如果我们从生活中的示例回到JavaScript的世界中来。

property指的是DOM的property,是元素属性。DOM中的节点事实上是一个对象,因此,可以添加自定义属性以及方法。使用对象访问属性的方式,可以访问到DOM节点的每一个property的属性。比如下面这个input元素:

<input id="name" name="user" class="form-control" myAttr="my-attri" value="w3cplus" data-control="text" />

我们使用.符号来获取或者重置DOM节点的property

这个时候,我们回过来查看input元素,对应的一些属性已被重置了,结果如下图所示:

从上面我们可以发现,对于自定义的attribute,如果通过.符号来获取,其值是null。同样的,自定义的property也不会出现在HTML的元素中,只会存在JavaScript中。另外,property的值可以是任何的数据类型,对大小写也敏感。

attribute是指标签属性,也就是HTML元素指定的属性,比如上面input元素中的idclass之类的。在浏览器的控制台中,可以通过attributes获取元素中所有的attribute。可以通过for循环,将对应的attribute打印出来,比如:

for (let i = 0; i < $0.attributes.length; i++) {
    console.log($0.attributes[i])
}

大家一看浏览器打印的结果就一目了然了:

从上面的操作结果来看:

attributeproperty的子集。

但不幸的是,浏览器并不是这样理解的。不过至于为什么,我也说不清楚,就不在这阐述了,以免误人子弟。

而W3C规范规定propertyattribute的含义却如下图所示:

从上图中可以看出来其分为三个部分:

Standard Attribute:标准属性(也被称为固有属性),比如示例中的idnameclass等DTD、Scheme中定义的标签属性。它的特点是,可以通过点方式或getAttribute都可以访问和重置。比如下图所操作的结果:

Custom Property:自定义属性,通过点方式访问、设置非DTD/Scheme中定义的标签属性。它的特点是仅能通过点方式操作属性。但在HTML的attribute中并无法显示出来,只能在JavaScript中显式。

Custom Attribute:自定义特性(显式特性),直接在HTML标签元素或者通过getAttribute(或setAttribute)访问、重置的非DTD/Scheme中定义的标签属性。其特点是可以在HTML标签中显式声明自定义特性,比如示例中的myAttr="my-attri"。另外可以通过getAttribute获取在HTML标签中设置的特性,以及使用setAttribute重置该特性。

查阅的一些文档,获知从IE8开始各大浏览器在这方面就遵守W3C标准。

attribute和property概念上的差异

如果仅从attributeproperty两单词上直译过来 —— “属性”。但为了更易于区分,更喜欢把attribute称为“特性”,property称为“属性”。回到JavaScript的DOM世界中来。先从他们的概念上来做一个简单的区分。

**attribute**是HTML标签上的某个属性,比如我们常见的idclassvalueonclick等属性,以及一些自定义的属性,比如大家熟悉的data-*,甚至像myAttr这样的自定义属性。比如:

<input id="name" name="user" class="form-control" myAttr="my-attri" value="w3cplus" data-control="text" />

在浏览器开发者工具中,通过properties可以查看到attributes具体的值,其对应的正好是HTML标签input中的attributes

回过头来看**properties**,其主要是JavaScript获取DOM对象上的属性值。而且它是作为JavaScript的基本对象。这个节点包括很多property,比如classListclassName之类的。比如下图:

从上图中,我们可以看出来,一个JavaScript对象有很多property,该集合名字为propertiesproperties里面有其他property以及attributes。而attributes里面有很多attribute,比如上面示例中的input元素中的idclass之类的。

在JavaScript中,DOM的property可以通过.符号或[]来获取,比如:

而DOM的attributes则可以通过setAttributegetAttributeremoveAttribute来做相应的处理,这个后面我们会做一些相关的介绍。

attributesproperties使用上的差异

通过上面的介绍,估计大家对attributesproperties或多或少有所了解了。但在实际的使用上还是略有差异的。我们来看看一些使用场景的差异性。

同样拿上面的input举例。在具体操作之前,简单的回忆和总结一下:

在HTML标签元素上的attribute,不管是标准的还是自定义的,它都是attributes这个Object的子集,而attributes又是properties的子集。同时,HTML标签元素上的标准的attribute同时也是DOM的property,它们也是properties的子集。

为了从语义上对其有所差异性的区分,把attribute称为HTML Attribute,译为特性,把property称为DOM Property,译为属性

在实际使用的时候,property通过.(或[])来访问HTML标签元素上的标准的attribute,也可以通过其来重置其值;但对于自定义的attribute通过.符号获取的值是undefined,不过可以通过.来重置它,需要注意的是,虽然重置了,但并不会修改HTML标签中自定义的attribute值,它只会存在JavaScript中。

对于HTML标签元素中的attribute,不管是标准的,还是自定义的,都可以通过getAttribute来获取,通过setAttribute来重置,还可以使用removeAttribute来删除。

先来看通过.符号获取、重置标准与非标准的attribute。结果如下:

我们再来看getAttributesetAttributeremoveAttribute对HTML标签的标准(和非标准的)attribute的操作:

通过for循环把操作过的attributes打印出来,看修改后的结果:

上面的小示例再次验证了:

propertyattribute对HTML标签的标准的attribute(比如,nameidclass)会相互影响;但property对于HTML标签的非标准的attribute做的相应修改,不会影响到HTML标签中的attribute,但会存在JavaScript的DOM中的property

上面的示例,看到的是propertyattribute对HTML标签原有的标准和非标准的attribute进行的操作。接下来看另一个场景,新增标准和非标准的属性。先来看property增加属性:

再来看看attribute增加属性。使用attribute给HTML标签增加属性,使用的是setAttribute方法。比如下图所示:

使用setAttribute给HTML标签添加attribute,不管是标准的,还是非标准的都能添加到HTML的标签中。比如上面的操作,我们通过for循环操作之后,可以看到元素inputattributes中包含了哪些attribute以及其对应的值:

虽然我们通过.符号或者getAttributesetAttribute可以获取和重置HTML的attribute。而且propertyattribute很多时候能做到一一对应,但有些属性还是无法相互影响的。比如inputvalue。接下来通过实际示例来阐述。

上图的结果,我想更易于说明一切。但也还有另我的场景,比如说,用户在input中输入了新的值,propertyattribute重新获取和重置的value将会是什么样的结果呢?我把整个过程录制下来了,大家可以看看其中的差异。

如果上图不好复原,咱们将上面的过程分步来看。

从上图的结果来看,用户在input新输入值之后,attribute通过getAttribute重新获取的value值依旧是HTML标签元素中attribute的值,但property并不一样,通过.符号获取的值就是用户新输入的值。

再来看第二种情形:

先用property重置inputvalue值,这个时候property.符号重获的value值是property重置后的值,但attributegetAttribute获取的还是HTML标签元素中attribute的值。接着用户在input中输入新的值,这个时候再次使用property获取value的值,从结果上可以看出来,获取到的是用户新输入后的值,但attribute还是依旧不变。

还有一种情况是,先用attributesetAttribute来重置inputvalue值,比如下图所示:

结果一目了然了,propertyattribute获取的值都是attribute重置后的value值。但用户在input中输入新的值,property获取的是用户新输入的值,而attribute还是最初setAttribute设置的value值。

简单的小结一下:

attributevalue值只在初始化的时候跟property一样,使用getAttribute获取的值是初始化的值,如果没有设置则是空,除非使用setAttribute手动去改变,但这个改变也不会影响到property的值。propertyvalue值是input实时输入的值,但该值的改变同样也不会影响attributevalue值。

上面看到的只是其中的一部分,其实还有很多场景也会略有不同。比如input这样的表单元素中的disabledchecked等属性,以及元素的hidden属性。这里就不再罗列了,感兴趣的同学可以自己在浏览器的控制台中,像上面这样一个一个尝试一下,我想只要你尝试了一定会很清晰的明白。下面简单的罗列几个常见的不同之处:

对于有些标准的特性的操作,element.getAttributeelement.property获取的值存在差异性。比如hrefsrcvaluestyleonclick等:

  • element.getAttribute获取的是href的实际值,element.property获取的是完整的url
  • element.property可以从element.setAttribute获得同步
  • element.getAttribute不能从element.property获得同步
  • element.getAttribute只能获得输入框的原始值,element.property可以获取输入框修改后的值
  • 对于checkbox时,未选中时,element.getAttribute返回的是nullelement.property返回的是false;反之,选中时,element.getAttribute仍返回nullelement.property返回的是true
  • 对于style标签,element.getAttribute返回的是string,而element.property返回的是object

除了有差异性之外,attributesproperties也有相同之处:

标准DOM的properties(DOM属性)与attributes(HTML Attribute,即标签特性)是同步的。公认的attributes会添加到DOM对象property上,比如idstyleclassNamedisabledchecked等。这时候直接操作property(也就是element.checked)或者使用element.getAttribute(或element.setAttribute)效果是一致的。但是参数不一定相同,比如element.classNameelement.getAttribute('class')两者获取的元素的class

总结

如果你要是阅读到这里的,说明你有足够多的耐性。花了不少的时间,听我胡扯许久,但我还是希望上面的内容没有对你们造成误解,或者对你们有所帮助。最后再花一点时间稍微总结一下下。

propertyattributies都是properties的子集,而每个attributeattributies的子集。attribute指的是HTML的Attribute,可以理解为HTML的特性,它们可以自定义,可以在HTML标签元素上添加attribute或者使用setAttribute添加(这两者添加的方式不一样,但结果一样)。大多数情况之下,HTML标签添加的都是attribute属性,property则是使用.符号进行更改。通常来讲,更自以为是相互影响(但也有不一样的地方,比如inputvalue)。另外,当添加的是非标准的属性时,propertyattribute是不互通的。除此之外,一些特殊属性则需要特殊对待。

在实际应用当中,大部分DOM操作都是使用properties来完成。但有些情形之下,使用attributes更为适合,比如:在自定义HTML的attributes,因为它并不同步到DOM的property。还有就是访问内置HTML的attributes(设置的初始值),attribute不能从property同步过来,典型的就是前面向大家展示的inputvalue

或许除了上述介绍的之外还有很多遗漏的地方,希望路过的大婶多多指点。如果你在这方面有更多的经验,欢迎在下面的评论中分享。要是你觉得文章对你有所帮助,也可以打赏哟(^_^)。

大漠

常用昵称“大漠”,W3CPlus创始人,目前就职于手淘。对HTML5、CSS3和Sass等前端脚本语言有非常深入的认识和丰富的实践经验,尤其专注对CSS3的研究,是国内最早研究和使用CSS3技术的一批人。CSS3、Sass和Drupal中国布道者。2014年出版《图解CSS3:核心技术与案例实战》。

如需转载,烦请注明出处:https://www.fedev.cn/javascript/dom-attributes-and-properties.htmljordan shoes for sale outlet UK