第二十课:js中如何操作元素的属性系统
本章的内容有点复杂,我将用简单的方式来介绍重要的东西,不重要的东西,这里就不讲了,讲了也毛用。
通常我们把对象的非函数成员叫做属性。对元素节点来说,其属性大题分为两大类,固有属性和自定义属性。固有属性拥有默认值,并且无法删除。自定义属性是用户随意添加的键值对。浏览器提供一组API来供人们操作自定义属性,即:setAttribute,getAttribute,removeAttribute,我们统称这组API为DOM属性系统。
DOM属性系统对属性名会进行小写处理,属性值会统一转字符串,举个例子:
div.setAttribute("xxx","1");
div.setAttribute("XxX","2");
div.setAttribute("XXx",3);
div.getAttribute("xxx");
div.getAttribute("XxX");
标准浏览器以及IE8以及以上浏览器会返回"3",因为属性名name先进行小写处理,所以第三个setAttribute会覆盖前面的属性设置,值被赋值为"3"。而取值时,也会把属性名name先进行小写处理,因此以上两个getAttribute都会返回"3"(会转换成字符串)。
但是IE6-7就很变态,第二个和第三个setAttribute不会覆盖第一个的设置,但是在取值时,也就是getAttribute时,第一个返回"1",第二个也返回"1"。本人又在IE7下去测试了一下:
var div = document.createElement("div");
div.setAttribute("xXx","1");
div.setAttribute("XXX",2);
console.log(div.getAttribute("xXx")); //"2"
console.log(div.getAttribute("XXX")); //"2"
简直是超级表态,对于超级变态的东西,没必要深究了,忽略IE6-7。记住上面的规则就OK了。
IE6-IE7在处理固有属性时,有时需要进行名字映射,比如:class变成className,for变成htmlFor。
元素内部撑起整个属性系统的attributes类数组属性
IE6-IE7中,attributes会包含上百个特性节点。不管你是用setAttribute定义的属性,还是以el.name = key定义的属性,还是没有定义的属性。在IE8和其他浏览器中,你只看到了寥寥可数的几个特性节点,这些被称为显式属性。
显式属性是被显式设置的属性,分两种情况:一种是写在标签内的HTML属性,一种是通过setAttribute动态设置的属性。这些属性不分固有的还是自定义的,只要设置了,都会出现在attributes中。在IE6-7中,我们可以通过特性节点的specified属性判定它是否被显式设置了。在IE8以及其他浏览器可以通过hasAttribute来判定属性是否被显式设置了。
因此有以下方法判定元素的属性是否是显示设置的属性:
var isSpecified = !!"1"[0] ? function(el, attr){ return el.hasAttribute(attr) } : function(el, attr){ var val = el.attributes[attr]; return !!val && val.specified }
在IE6-7下"1"[0]返回false,而IE8和其他浏览器返回true。
HTML5对属性也进行了分类,dataset对象装载着所有以data-开头的自定义属性。classList装载着元素的所有类名。formData装载着所有要提供到后台的数据,以表单元素name值与value值构成的不透明对象(不能通过for in进行循环遍历)。表单元素的form属性总是指向其外围的表单对象form。
如何区分固有属性与自定义属性
IE下,元素节点的attributes对象有一种名为expando的的布尔属性,可以判定它是否为自定义属性。
function isCustomAttribute(attr, elem){ //true就代表attr是elem的自定义属性
var attrs= elem.attributes;
return attrs[attr] && attrs[attr].expando == true;
}
但是标准浏览器没有名为expando的布尔属性。
兼容性的写法如下:
function isCustomAttribute(attr,elem){
elem = elem || document.createElement("div"); //有些属性只有特殊元素才会有,这时才需要传入这个元素。一般的属性,直接用div元素
return elem.getAttribute(attr) === null && elem[attr] === undefined;
}
只有自定义属性,在div元素下,会返回true。如果是固有属性,在div元素下,不会全部满足条件,返回false。如果是其他特殊的属性,比如:checked,这时需要传入元素节点type为radio的input(此input没有设置checked属性,最好是一个新创建的input元素,因为如果你传入一个已经通过setAttribute(checked,null),设置的input,那么测试就会有兼容性问题了),这时也不会全部满足条件,返回false。如果是name属性,直接用div来测试,这时return也会是false,因为name是固有属性。如果你把chaojidan这个名字传进去,那么以上就会return true,表明chaojidan不是固有属性。
这里需要明白的一点就是,elem参数一般不需要,如果你设置了一个div1的chaojidan = "chaojidan",然后调用isCustomAttribute(chaojidan,div1),那么就测试不出来了。因为你已经在div1上设置了属性值chaojidan了,那么你getAttribute(chaojidan)时,就会返回"chaojidao"了。你只需要调用isCustomAttribute(chaojidan)就行了,这时返回的就是true。这个方法的第二个参数,是针对div没有的属性值来设置的。
综上所述:
进行属性判定时,必须确保元素没有设置此属性,最好是新创建的元素。
如何判定浏览器是否区分固有属性和自定义属性
jQuery中通过以下方法来判断:
el.setAttribute("className","t");
el.className !== "t";
如果区分固有属性和自定义属性,以上会返回true。因为如果区分的话,el.setAttribute("className","t")设置的是自定义属性className,这时通过el.className会取到元素节点的class属性,而el的class属性没有设置值是undefined,因此返回true。但是在IE6-7下,是不区分固有属性和自定义属性,因此以上el.className会取到"t",返回false。
这里再介绍一些知识点:
大家在看源码的时候,可能会看到getAttribute(name,4)这种用法,但是getAttribute只接受一个参数的。其实接受第二个参数是IE的专有方法。
在IE下,getAttribute的第二个参数有4个预设值:0是默认情况。1属性名区分大小写。2取出源代码中的原字符串值(IE6-7对动态创建的节点无效,IE6-8对布尔属性无效)。4用户href属性,取得完整路径。这里无须知道IE几下支持,只要知道有这么一个东西就行了,看源码时,至少可以看得懂。
操作class的一些工具方法:
var getClass = function(elem){
return elem.className.replace(/\s+/," ").split(" "); //replace方法,会把类名中多余的空字符串清除掉,然后通过split方法,把类名组装成数组返回。
}
var hasClass = function(elem,cls){
return -1 < (" "+elem.className+" ").indexOf(" "+cls+" "); //空格隔开,才能确保cls是独立的字符串。
}
var addClass = function(elem,cls){
if(!hasClass(elem,cls)) elem.className + = " " + cls;
}
var removeClass = function(elem,cls){
if(hasClass(elem,cls)){
var reg = new RegExp('(\\s|^)'+cls+'(\\s|$)');
//此正则前半部分\\s,因为是new RegExp,所以\需要转义,其实\\s就是\s,只不过s前面的\需要转义。|是或的意思,^是开始标识。后半部分$是结束标识
elem.className = elem.className.replace(reg," "); //之所有用此正则,因为cls可能在最前面(匹配^+cls),最后面(cls+$),最中间(\s+cls+\s)
}
}
var clearClass = function(elem,cls){
elem.className = "";
}
在HTML5中,元素添加了一个classList属性对象,这个属性对象有add,toggle,remove,contains方法来操作class属性。
数组some和every方法的区别:
array1.some(callbackfn,thisArg)接受两个参数,
callbackfn
必需。 一个接受最多三个参数的函数。 some 方法会为 array1 中的每个元素调用 callbackfn 函数,直到 callbackfn 返回 true(array1.some返回true),或直到到达数组的结尾(array1.some返回false)。
thisArg
可选。 可在 callbackfn 函数中为其引用 this 关键字的对象。 如果省略 thisArg,则 undefined 将用作 this 值。
some 方法会按升序索引顺序对每个数组元素调用 callbackfn 函数,直到 callbackfn 函数返回 true。 如果找到导致 callbackfn 返回 true 的元素,则 some 方法会立即返回 true。 如果回调不对任何元素返回 true,则 some 方法会返回 false。
不为数组中缺少的元素调用该回调函数。([1,2,"",3,4]),数组的第三项不会执行回调方法
除了数组对象之外,some 方法可由具有 length 属性且具有已按数字编制索引的属性名的任何对象使用。(arguments,jQuery对象等)
function callbackfn(value, index, array1),可使用最多三个参数来声明回调函数。
every方法跟some方法很相似,除了返回值的条件不一样:
every 方法会按升序顺序对每个数组元素调用一次 callbackfn 函数,直到 callbackfn 函数返回 false。 如果找到导致 callbackfn 返回 false 的元素,则 every 方法会立即返回 false。 否则,every 方法返回 true。
综上所述:some方法,只要数组中有一个让回调方法返回true,就返回true。every方法,数组中的每一个都让回调方法返回true,才返回true。
加油!
第二十课:js中如何操作元素的属性系统的更多相关文章
- 在js中获取页面元素的属性值时,弱类型导致的诡异事件踩坑记录,
前几天写一个js的时候遇到一个非常诡异的事情,这个问题是这样的,我要获取一个页面的DOM元素的val值,判断这个值是否比某个变量大,这个需求原先数字最大也就是10,现在要改了,可能会更多,这个时候我发 ...
- NeHe OpenGL教程 第二十课:蒙板
转自[翻译]NeHe OpenGL 教程 前言 声明,此 NeHe OpenGL教程系列文章由51博客yarin翻译(2010-08-19),本博客为转载并稍加整理与修改.对NeHe的OpenGL管线 ...
- JQuery中操作元素的属性_对象属性
我们主要是通过attr去获取元素的属性: 看body内容: <body> <p> 账号:<input type="text" id="una ...
- Kali Linux Web 渗透测试视频教—第二十课-利用kali linux光盘或者usb启动盘破解windows密码
Kali Linux Web 渗透测试视频教—第二十课-利用kali linux光盘或者usb启动盘破解windows密码 文/玄魂 目录 Kali Linux Web 渗透测试视频教—第二十课-利用 ...
- Kali Linux Web 渗透测试— 第二十课-metasploit.meterpreter
Kali Linux Web 渗透测试— 第二十课-metasploit.meterpreter 原文链接:http://www.xuanhun521.com/Blog/7fc11b7a-b6cb-4 ...
- js中常用追加元素的几种方法
<!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title> ...
- js中如何操作json数据
一.要想熟练的操作json数据,就先要了解json数据的结构,json有两种结构:对象和数组. 1.对象 一个对象以“{”开始,“}”结束.每个“名称”后跟一个“:”:“‘名称/值’ 对”之间使用“, ...
- JS中对数组元素进行增删改移
在js中对数组元素进行增删改移,简单总结了一下方法: 方法 说明 实例 push( ); 在原来数组中的元素最后面添加元素 arr.push("再见58"); unshift( ) ...
- 从零开始学习jQuery (四) 使用jQuery操作元素的属性与样式
本系列文章导航 从零开始学习jQuery (四) 使用jQuery操作元素的属性与样式 一.摘要 本篇文章讲解如何使用jQuery获取和操作元素的属性和CSS样式. 其中DOM属性和元素属性的区分值得 ...
随机推荐
- [转载]UEditor报错TypeError: me.body is undefined
本文转载来自:UEditor报错TypeError: me.body is undefined 今天在使用UEditor的setContent的时候报错,报错代码如下 TypeError: me.bo ...
- 虚拟机centos6.5 --设置静态ip
编辑网卡文件,vi /etc/sysconfig/network-scripts/ifcfg-eth0修改以下内容: ONBOOT=no #改为yes, BOOTPROTO=dbcp #改为stati ...
- redis master配置了密码进行主从同步
1.如果master不设置密码,那么直接在slave服务器配置slaveof即可 配置如下 #slaveof ip 端口 slaveof 配置好我们看下redis的日志 看是否同步成功 :S Jan ...
- seq 显示00 01的格式
for i in `seq -w 00 20` ; do echo $i ;done 00 01 02 03 04 05 06 07 08 09 10 11 12 13 14 15 16 17 18 ...
- opencv 3.0 DPM Cascade 检测 (附带TBB和openMP加速)
opencv 3.0 DPM cascade contrib模块 转载请注明出处,楼燚(yì)航的blog,http://www.cnblogs.com/louyihang-loves-baiyan/ ...
- 【温故而知新-Javascript】使用 Document 对象
Document 对象时通往DOM功能的入口,它向你提供了当前文档的信息,以及一组可供探索.导航.搜索或操作结构与内容的功能. 我们通过全局变量document访问Document对象,它是浏览器为我 ...
- 《The Django Book》实战--第二章--动态网页基础
这章演示了一些最基本的Django开发动态网页的实例,由于版本不一样,我用的是Django 1.,6.3,有些地方按书上的做是不行的,所以又改了一些,写出来让大家参考. 这是一个用python写的一个 ...
- Android配置----Eclipse+BlueStacks调试Android应用
[声明] 欢迎转载,但请保留文章原始出处→_→ 生命壹号:http://www.cnblogs.com/smyhvae/ 文章来源:http://www.cnblogs.com/smyhvae/p/3 ...
- java 15 -7 ListIterator 的特有方法
列表迭代器: ListIterator listIterator():List集合特有的迭代器 该迭代器继承了Iterator迭代器,所以,就可以直接使用hasNext()和next()方法. 特有 ...
- Android签名机制:生成keystore、签名、查看签名信息
转自:http://www.ourunix.org/post/146.html