第二十课: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属性和元素属性的区分值得 ...
随机推荐
- List与Set的使用
接口Collection: Collection是Java的一个集合框架, 也是一个根接口.JDK中没有提供此接口的任何实现,但是提供了更具体的子接口Set和List接口的实现,所有的Collecti ...
- NOIP2008 普及组T1 ISBN号码 解题报告-S.B.S.
题目描述 每一本正式出版的图书都有一个ISBN号码与之对应,ISBN码包括9位数字.1位识别码和3位分隔符,其规定格式如“x-xxx-xxxxx-x”,其中符号“-”就是分隔符(键盘上的减号),最后一 ...
- js计算系统当前日期是星期几的几种方法
方法一: // 计算系统当前是星期几 var str = "今天是星期" + "日一二三四五六".charat(new date().getday()); 方法 ...
- .Net Framework 4.0 内部排序探索
简介 一时好奇心起,想一窥.Net Framework 4.0内部究竟是使用何种算法排序.以前听人说Framework内部是使用的快速排序,但究竟耳听为虚,眼见为实.主要通过JetBrains dot ...
- JMeter学习(三十一)Access Log Sampler
前提: 在tomcat\conf\server.xml默认情况下,会有一段代码: <Valve className="org.apache.catalina.valves.Access ...
- java14-9 Doteformat的练习
需求: 键盘录入出生年月日,计算出距离现在已经生活了几天 分析: A:创建键盘录入固定模式的字符串 B:计算步骤: a:把输入进来的字符串格式化成日期 b:获取现在的日期,减去格式化后的日期 c:把得 ...
- javascript之享元模式
实现享元模式的一般步骤: 1.将所有外在数据从目标类中剥离.具体做法是尽可能多的删除该类的属性,所删除的应该是那种因实例而异的属性.构造函数的参数也要这样处理,这些参数应该被添加到该类的各个方法. 这 ...
- 14Mybatis_输入映射(传递pojo的包装对象)——很重要
假设我们有这么一个需求:用户信息的综合查询,需要传入的查询条件很复杂(可能包括用户信息,其他的信息,比如商品,订单) 我们的思想是:传入到select中的parameterType是一个包装类,里面可 ...
- heartbeat初探
1,概念及原理 http://www.mingxiao.info/tag/heartbeat/
- C语言 位运算
1G=1024M; 1M=102KB; 1KB=1024B(字节); 1B=8bits(位); #include<stdio.h> #include<stdlib.h> //C ...