这两天一直在看DOM元素的attribute
和property
,简单让人晕。从直译上,我一开始都理解为“属性”,而且对于我这样的新手,将两者混淆在一起,傻傻的分不清楚。后来经过大大们的指点,知道两者是不同的东西,但两者之间又有紧密的联系。为了能更清晰的整明白两者的关系与不同,所以把自己理解和搜集的资料理了一下,希望对新手有所帮助。
Attribute和property形象上的描述
文章开头也说了,自己对attribute
和property
两者理不清楚,在搜集两者差异的时候,看到了Web技术研究所站长对两者的描述,简值是绝了,让初学者一看就易于理解,下面这部分内容直接复制过来了。
attribute
和property
都被翻译成“属性”,但是它们有着本质上的区别。拿生活中的示例来说,或许对于像我这样的新手更易于理解。
“桌子上有个苹果”。attribute
仅仅是描述了这个“有苹果”的事实,而property
则是直指那个桌子上的苹果。这里的苹果是一个实体,用attribute
来描述只能说明这个事件的事实。它无法准确的描述出具体哪个苹果在桌子上。再举个示例 —— “我爸是李刚”。attribute
仅仅是描述了“李刚”这个名字,而property
则是直接代表“李刚”这个人(一个实体)。叫“李刚”这个名字的人很多,所以attribute
无法确切表示。而property
则是直指实体的,可以准确描述事物。但也不是说attribute
就绝对无法准确表示事物,只是attribute
只能用文字描述,所以它要精确描述一个东西的代价是比property
高了许多。比如描述“李刚”可以用他的身份证号码之类的,可是说不定人家的身份证还是伪造的,所以还需要更多的文字描述才能准确的说明一个东西。
那么既然property
比attribute
好,为什么还需要attribute
呢?就说“我爸是李刚”这件事吧,过了这么多年了也许很多人都忘了。property
是保存在记忆(比如计算机的内存memory
)中的,虽然一开始很准确,但是无法长期保存。我们经常会把需要长期保存的东西用文字描述下来,这时就需要用到attribute
。而且attribute
和property
并不冲突,我们经常会翻阅一些旧资料来补充我们渐淡的记忆。
这些就是它们本质上的区别,在程序中我们可以用另外的方式说明它。attribute
是标记语言的概念(比如HTML语言),而标记语言本身就是一种文本,所以attribute
这种文本描述的性质在标记语言中很容易使用。而property
则是保存在内存中,而内存会随着程序运行结束被释放,因此变得无法长期储存。在JavaScript中,DOM对象通常都是多重继承的。同时继承了HTML和JavaScript的Object
。Object
是完完全全的内存对象,所以使用的是property
,而HTML本身就是标记语言,所以使用的是attribute
。当这两个东西被继承到同一个对象上的时候经常会让人混淆起来。由于一些attribute
是很常用的,比如id
、class
等,所以DOM把它们映射到property
上以方便使用。这样我们就会遇到一个对象同时具有id
这个attribute
和property
(由于class
是保留字,所以它被映射到property
上时变成className
)。
虽然被DOM这样一搞,初学者易于混淆attribute
和property
。但上面的比喻,估计有帮助初学者易于理解。但要更清晰的理解,还是有必要通过示例来阐述。接下来,我们回到我们的代码世界当中。
attribute和property的定义
其实上面的示例描述,对attribute
和property
已经定义的非常清晰。如果我们从生活中的示例回到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
元素中的id
、class
之类的。在浏览器的控制台中,可以通过attributes
获取元素中所有的attribute
。可以通过for
循环,将对应的attribute
打印出来,比如:
for (let i = 0; i < $0.attributes.length; i++) {
console.log($0.attributes[i])
}
大家一看浏览器打印的结果就一目了然了:
从上面的操作结果来看:
attribute
是property
的子集。
但不幸的是,浏览器并不是这样理解的。不过至于为什么,我也说不清楚,就不在这阐述了,以免误人子弟。
而W3C规范规定property
和attribute
的含义却如下图所示:
从上图中可以看出来其分为三个部分:
Standard Attribute:标准属性(也被称为固有属性),比如示例中的id
、name
、class
等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概念上的差异
如果仅从attribute
和property
两单词上直译过来 —— “属性”。但为了更易于区分,更喜欢把attribute
称为“特性”,property
称为“属性”。回到JavaScript的DOM世界中来。先从他们的概念上来做一个简单的区分。
attribute
是HTML标签上的某个属性,比如我们常见的id
、class
、value
和onclick
等属性,以及一些自定义的属性,比如大家熟悉的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
,比如classList
、className
之类的。比如下图:
从上图中,我们可以看出来,一个JavaScript对象有很多property
,该集合名字为properties
,properties
里面有其他property
以及attributes
。而attributes
里面有很多attribute
,比如上面示例中的input
元素中的id
、class
之类的。
在JavaScript中,DOM的property
可以通过.
符号或[]
来获取,比如:
而DOM的attributes
则可以通过setAttribute
、getAttribute
和removeAttribute
来做相应的处理,这个后面我们会做一些相关的介绍。
attributes
和properties
使用上的差异
通过上面的介绍,估计大家对attributes
和properties
或多或少有所了解了。但在实际的使用上还是略有差异的。我们来看看一些使用场景的差异性。
同样拿上面的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
。结果如下:
我们再来看getAttribute
、setAttribute
和removeAttribute
对HTML标签的标准(和非标准的)attribute
的操作:
通过for
循环把操作过的attributes
打印出来,看修改后的结果:
上面的小示例再次验证了:
property
和attribute
对HTML标签的标准的attribute
(比如,name
、id
、class
)会相互影响;但property
对于HTML标签的非标准的attribute
做的相应修改,不会影响到HTML标签中的attribute
,但会存在JavaScript的DOM中的property
。
上面的示例,看到的是property
和attribute
对HTML标签原有的标准和非标准的attribute
进行的操作。接下来看另一个场景,新增标准和非标准的属性。先来看property
增加属性:
再来看看attribute
增加属性。使用attribute
给HTML标签增加属性,使用的是setAttribute
方法。比如下图所示:
使用setAttribute
给HTML标签添加attribute
,不管是标准的,还是非标准的都能添加到HTML的标签中。比如上面的操作,我们通过for
循环操作之后,可以看到元素input
的attributes
中包含了哪些attribute
以及其对应的值:
虽然我们通过.
符号或者getAttribute
、setAttribute
可以获取和重置HTML的attribute
。而且property
和attribute
很多时候能做到一一对应,但有些属性还是无法相互影响的。比如input
的value
。接下来通过实际示例来阐述。
上图的结果,我想更易于说明一切。但也还有另我的场景,比如说,用户在input
中输入了新的值,property
和attribute
重新获取和重置的value
将会是什么样的结果呢?我把整个过程录制下来了,大家可以看看其中的差异。
如果上图不好复原,咱们将上面的过程分步来看。
从上图的结果来看,用户在input
新输入值之后,attribute
通过getAttribute
重新获取的value
值依旧是HTML标签元素中attribute
的值,但property
并不一样,通过.
符号获取的值就是用户新输入的值。
再来看第二种情形:
先用property
重置input
的value
值,这个时候property
的.
符号重获的value
值是property
重置后的值,但attribute
的getAttribute
获取的还是HTML标签元素中attribute
的值。接着用户在input
中输入新的值,这个时候再次使用property
获取value
的值,从结果上可以看出来,获取到的是用户新输入后的值,但attribute
还是依旧不变。
还有一种情况是,先用attribute
的setAttribute
来重置input
的value
值,比如下图所示:
结果一目了然了,property
和attribute
获取的值都是attribute
重置后的value
值。但用户在input
中输入新的值,property
获取的是用户新输入的值,而attribute
还是最初setAttribute
设置的value
值。
简单的小结一下:
attribute
的value
值只在初始化的时候跟property
一样,使用getAttribute
获取的值是初始化的值,如果没有设置则是空,除非使用setAttribute
手动去改变,但这个改变也不会影响到property
的值。property
的value
值是input
实时输入的值,但该值的改变同样也不会影响attribute
的value
值。
上面看到的只是其中的一部分,其实还有很多场景也会略有不同。比如input
这样的表单元素中的disabled
、checked
等属性,以及元素的hidden
属性。这里就不再罗列了,感兴趣的同学可以自己在浏览器的控制台中,像上面这样一个一个尝试一下,我想只要你尝试了一定会很清晰的明白。下面简单的罗列几个常见的不同之处:
对于有些标准的特性的操作,element.getAttribute
和element.property
获取的值存在差异性。比如href
、src
、value
、style
和onclick
等:
element.getAttribute
获取的是href
的实际值,element.property
获取的是完整的url
element.property
可以从element.setAttribute
获得同步element.getAttribute
不能从element.property
获得同步element.getAttribute
只能获得输入框的原始值,element.property
可以获取输入框修改后的值- 对于
checkbox
时,未选中时,element.getAttribute
返回的是null
,element.property
返回的是false
;反之,选中时,element.getAttribute
仍返回null
,element.property
返回的是true
- 对于
style
标签,element.getAttribute
返回的是string
,而element.property
返回的是object
除了有差异性之外,attributes
和properties
也有相同之处:
标准DOM的
properties
(DOM属性)与attributes
(HTML Attribute,即标签特性)是同步的。公认的attributes
会添加到DOM对象property
上,比如id
、style
、className
、disabled
和checked
等。这时候直接操作property
(也就是element.checked
)或者使用element.getAttribute
(或element.setAttribute
)效果是一致的。但是参数不一定相同,比如element.className
和element.getAttribute('class')
两者获取的元素的class
。
总结
如果你要是阅读到这里的,说明你有足够多的耐性。花了不少的时间,听我胡扯许久,但我还是希望上面的内容没有对你们造成误解,或者对你们有所帮助。最后再花一点时间稍微总结一下下。
property
和attributies
都是properties
的子集,而每个attribute
是attributies
的子集。attribute
指的是HTML的Attribute
,可以理解为HTML的特性,它们可以自定义,可以在HTML标签元素上添加attribute
或者使用setAttribute
添加(这两者添加的方式不一样,但结果一样)。大多数情况之下,HTML标签添加的都是attribute
属性,property
则是使用.
符号进行更改。通常来讲,更自以为是相互影响(但也有不一样的地方,比如input
的value
)。另外,当添加的是非标准的属性时,property
和attribute
是不互通的。除此之外,一些特殊属性则需要特殊对待。
在实际应用当中,大部分DOM操作都是使用properties
来完成。但有些情形之下,使用attributes
更为适合,比如:在自定义HTML的attributes
,因为它并不同步到DOM的property
。还有就是访问内置HTML的attributes
(设置的初始值),attribute
不能从property
同步过来,典型的就是前面向大家展示的input
的value
。
或许除了上述介绍的之外还有很多遗漏的地方,希望路过的大婶多多指点。如果你在这方面有更多的经验,欢迎在下面的评论中分享。要是你觉得文章对你有所帮助,也可以打赏哟(^_^)。
如需转载,烦请注明出处:https://www.w3cplus.com/javascript/dom-attributes-and-properties.html