这两天一直在看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)}大家一看浏览器打印的结果就一目了然了: 从上面的操作结果来看: 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。
原文: https://www.w3cplus.com/javascript/dom-attributes-and-properties.html © w3cplus.com
点击有惊喜
|