js原生操作HTML对象的属性区别

在之前的文章中,有提到过,使用对象直接获取HTML元素的属性值,和使用DOM方法获取,是有区别的,而且在有些浏览器下,如果使用的方法不对,那么会导致兼容性错误。

原文请查看:display的问题

当时对这个问题的理解相对较浅,现在针对这个方面再次进行说明。

一:操作HTML元素属性的方法

通常情况下,我们使用的方法有两种:(假设我们获取到的HTML对象是obj)

  • 1,对象方法,例如obj.id,取得目标obj的属性id的值。
  • 2,DOM方法,使用obj.getAttribute("id"),同样能获取到id的值。

当然还有其他的方法,只是不常用而已,比如obj.attributes["id"]这样的取值方法这个方法的实质就是和上面提到的dom方法是相同的,这里采用的是对象直接取值,而上面的dom方法,是使用封装好的API进行取值,在下面的讨论中,你可以看到他们相同的根本原因。。这里就不讨论方法的多少了,只要会使用其中之一并解决所有的兼容问题,那就可以了。

下面的内容就是基于这两种常用的方法,进行的说明。

二:两种方法的区别

在之前的文章中,有说过这么一段话:style属性的操作最优方法是直接对象中利用style属性的cssText;其他元素自带一般属性的操作方法是直接对象的方法;元素的自定义属性的最优操作方法是dom方法。

两种取值方法的区别,以及主要的表现形式,可以这样描述,对于常用的属性,比如:id,class等,使用第一种方法obj.id取值,是最方面的,首先,看起来直接明了,写法也简单,也没有什么兼容性问题,当然class的取值要写成obj.className,这样大家应该都知道的。因为有时候,我们也会给标签加一些自定义的属性,方便之后对该标签进行操作时,进行区分。那么这个时候的取值,最好就使用obj.getAttribute这种方法了。

1:读取已有的属性


<div id="select" class = "class" data-data = "data" aaa = "aaa"></div>
var obj = document.getElementById("select");
//下面分别使用两种方法,获取对应的值
console.log(obj.className);  //class
console.log(obj["data-data"]);//undefined
console.log(obj.dataset.data);//data-data属性,是HTML5中新支持的属性,使用这样的方法进行获取,obj.dataset是一个对象,可以存储多个属性的值,支持这个属性的浏览器返回值是“data”,不支持dataset属性的,浏览器会抛出异常。IE9没有这个属性,IE10+的未测试。
console.log(obj.aaa);         //undefined 
console.log("aaa" in obj);    //结果是undefined,对象检测属性是否存在的,由这里可以看出,自定义的属性,是不会存在于obj对象的直接子属性中的。注:IE8-的模式下,这里的结果是true,这应该是因为,IE8-的浏览器中,HTML的DOM标签对象,并不是继承自Object对象的原因吧。所以在HTML标签上面,添加的属性,都会被添加到对应标签的对象上面去,这个是使用该种方法的一个差异之处。


接下来使用另外一种方法:


console.log(obj.getAttribute("class"));     //class
console.log(obj.getAttribute("data-data")); //data
console.log(obj.getAttribute("aaa"));       //aaa


这是没有什么问题的,都可以获取到正确的值,但是我们这里只是针对的在标签中,设置好的属性了。

那这是什么原因呢?那我们先看下,这个obj包含的一个属性吧,我们很熟悉的一个属性,attributes,请看下面的图示:

从上图中,可以看出什么呢?attributes的属性,和HTML标签中设置的属性是完全一样的。OK,然后你是不是可以想想,为什么这两种方法是有差别的了?

2:对标签使用两种方法设置属性


<div id="select"></div>
var obj = document.getElementById("select");


使用第一种方法设置:


obj.className = "class";     //没问题,在所有浏览器下都设置成功。
obj['data-data']= "data1";   //IE8-的浏览器下,设置成功,其他都不行。
//obj.dataset.data= "data2"; //支持dataset的,都可以。
obj.aaa = "aaa";             //IE8-的浏览器下,设置成功,其他都不行。


主要看下,设置后的浏览器显示的图示吧:

支持dataset方法的浏览器,经过上面的属性设置之后,HTML标签的属性集合是这样的:

从图中也可以看出,对于obj本身不具备的属性,是不能通过这种方法进行属性值的设置的。

OK,第二种方法设置:


obj.setAttribute("class","class");
obj.setAttribute("data-data","data");
obj.setAttribute("aaa","aaa");


没有什么问题,全部设置成功了。查看设置之后的结构图:

从图中可以看出,新添加的属性,在HTML结构中,是直接添加到标签中了,在HTML的对象中,是添加到了attributes属性中了,至于obj的本身属性,比如className是添加了,我们这里可以通过obj.className进行获取新添加的class,但是对于obj本身并不存在的属性,是不能添加的,所以,如果你不能确定,你所使用的属性是不是obj本身自带的属性,那么还是使用setAttributegetAttribute进行操作属性吧。

这里,为什么使用getAttribute可以获取attributes内的值,其实就是getAttributeHTML对象继承来的一个方法,你可以这样检测是不是:console.log("getAttribute" in obj);//true,如果返回true,就说明这是obj对象中,包含这个方法。

那这样的话,就很容易想象一下了,想想我们看到过的模块化方面的知识,对于一个对象,我们只提供一个接口是对外的,其内部的实现过程,我们并不考虑。模块化这个地方,东西还很多,也不是一两句话可以解释的。我们可以举个例子,把这个进行简单的模拟。

首先,我们先定义一个obj对象,并且对该对象添加一个attributes的属性,和两个用来操作该属性的方法,getAttributesetAttribute


var obj = {
	attributes:{},
	setAttribute:function(name,value){},
	getAttribute:function(name){}
};


写添加的setAttribute的方法:


setAttribute:function(name,value){
    //首先,要先获取添加的属性的存放位置。
    var attr = this.attributes;
    //检查新添加的方法,是不是已经存在,如果不存在,则进行添加
    if(name in attr){
	//对于我们这里,检查这个其实可有可无,因为不管是有没有存在,添加值是使用的同样的方法,但这个检测在写代码时,都是要考虑的,所以就加这么一个无意义的判断吧。
	attr[name] = value;
    }else{
	attr[name] = value;
    }
}


getAttribute的方法:


getAttribute:function(name){
    //首先,要先获取添加的属性的存放位置。
    var attr = this.attributes;
    //检查新添加的方法,是不是已经存在,如果不存在,则进行添加
    if(name in attr){
	return attr[name];
    }else{
	return undefined;
    }
}


这样不就实现了这最基本的方法?你可以点击:查看demo,这上面的例子,是最简单的那种,没有进行任何的处理,单纯的只是为了完成这块功能。

不过从这段代码中,你应该也可以想象一下,HTML对象中,获取属性的getAttribute的实现原理了吧。
那下面我们做这样的修改。


var obj = {
    attributes:{},
    id:undefined,
    setAttribute:function(name,value){},
    getAttribute:function(name){}
};


这里我添加了一个obj的属性,id,我希望如果这个值修改的时候,obj.idobj.getAttribute("id")有相同的值。
这个时候,就得修改两个方法的的内部实现了,如果你有兴趣了解这些,直接点击:查看demo,然后查看源码吧。

想想,有时候,当一个对象包含的属性太多太多,但是其中大部分属性使我们不需要使用的,我们甚至不想知道,这些属性代表什么,执行了什么功能,那么如果我们能把这些属性当成私有属性,只提供我们想要的方法的API,不是更简单吗?这个时候,就要把该对象进行模块化了,那怎么进行模块化呢,这个方法比较多吧,这里只使用一个最简单的方法:


var obj = (function(){
    var attributes={},
	id=undefined;
    
    function setAttribute(name,value){}
    function getAttribute(name){}
    return {
        id:id,
	set:setAttribute,
        get:getAttribute
    };
})();


看下这个时候的obj对象,这个对象现在供我们可操作只有这三个变量,像attributes就成为obj的内部属性了,只有内部的方法才能过调用,这样就可以保证attributes只有通过返回的getset方法可以操作,保证attributes的值不会被恶意的修改。并且,有没有觉得这样写,会让整个API显得更加的简单呢?这种也是闭包的一种应用吧,虽然有些变量已经脱离了自己的作用域,但是依旧被一些方法在使用,所以会一直存在,当然,这里也只能通过特定的方法进行操作这些变量,如果想要了解闭包的相关知识,请自己查阅吧。

如果想要查看的话,就直接点击:查看demo,然后查看源码吧。

OK,这里就说这些吧,用上面的这个简单的例子应该能明白,HTML对象中,属性的不同取值方法的差别来自哪里了吧。

当然,如果你使用的框架的话,那就不需要担心这些问题了,因为框架把这些问题都解决了。例如jquery中的属性操作:attrprop两种方法,有兴趣的可以点击查看

如果发现文中的问题,希望您能提出来,谢谢啦。

本文地址:http://www.zhangyunling.com/?p=28

发表评论

电子邮件地址不会被公开。 必填项已用*标注

您可以使用这些HTML标签和属性: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>

js原生操作HTML对象的属性区别》有11个想法

  1. Lee说道:

    不可以分享的?评论都是英文,我的好突兀

    1. yunling_zhang说道:

      别提了,上面的那些就成都是假的吧,当时没有评论的过滤插件,后来就没有再处理。

      你说的是快速分享的吗?很多东西页面都没有添加~~平常比较少有时间改风格功能什么的,只能写点东西。

      分享的功能,之后找时间加上吧,感谢建议。

  2. royal blue foamposites说道:

    I go to see daily a few blogs and blogs to read content, except this web site provides feature based writing js原生操作HTML对象的属性区别 | 引领前端 .

  3. kids toms说道:

    Great article, thank you. I signed to your blog rss feed.

  4. beats by dr dre beatbox说道:

    Wonderful solutions.Id like to recommend checking out a lot around the idea of french fries. What exactly are you looking for though?

  5. monster beats official说道:

    Thanks for any other informative site. Where else may I get that type of info written in such a perfect approach? I have a mission that I’m simply now running on, and I’ve been on the look out for such info.

    1. yunling_zhang说道:

      This is just a personal blog, To write some of my personal ideas. you want to seek some other blogs like this? zhangxinxu.com/wordpress/, this blog write mainly about CSS , and I think its very good! If I has a wrong understand your means, please tell me, thank you!

  6. Hello there, You have done a fantastic job. I will certainly digg it and in my view suggest to my friends. I’m sure they’ll be benefited from this site.
    [url=http://allstar.allshop.jp]

    1. yunling_zhang说道:

      thanks for your reply. Welcome to tell me some Suggestions when you found any problems in my papers, we can discuss it and get progress together.

  7. Thank you, I have just been looking for info approximately this topic for a while and yours is the greatest I have came upon till now. However, what about the bottom line? Are you certain about the source?|What i don’t understood is in truth how you’re not really much more well-appreciated than you might be right now. You’re so intelligent.
    [url=http://www.kukoven.com/]

    1. yunling_zhang说道:

      Thank you. The content of this article is my personal idea. I can not ensure it can work perfect in all browsers. I tested the current mainstream browsers when i write this article,and I has not found any problem. I think it is safe to use, and thanks for your reply.