富贵资源网 Design By www.hznty.com
先来看一下代码:(支持多个class查询和在某个范围内进行查询)
复制代码 代码如下:
/*
* 根据元素clsssName得到元素集合
* @param fatherId 父元素的ID,默认为document
* @tagName 子元素的标签名
* @className 用空格分开的className字符串
*/
function getElementsByClassName(fatherId,tagName,className){
node = fatherId&&document.getElementById(fatherId) || document;
tagName = tagName || "*";
className = className.split(" ");
var classNameLength = className.length;
for(var i=0,j=classNameLength;i<j;i++){
//创建匹配类名的正则
className[i]= new RegExp("(^|\\s)" + className[i].replace(/\-/g, "\\-") + "(\\s|$)");
}
var elements = node.getElementsByTagName(tagName);
var result = [];
for(var i=0,j=elements.length,k=0;i<j;i++){//缓存length属性
var element = elements[i];
while(className[k++].test(element.className)){//优化循环
if(k === classNameLength){
result[result.length] = element;
break;
}
}
k = 0;
}
return result;
}
好,我们来测试一下:
复制代码 代码如下:
<div id="container">
<span class="aaa zzz ccc"></span>
<div class="aaa bbb ccc"></div>
</div>
<div class="aaa bbb ccc"></div>
复制代码 代码如下:
window.onload = function(){
alert(getElementsByClassName(document,"div","aaa ccc").length);//2
alert(getElementsByClassName("container","div","aaa ccc").length);//1
alert(getElementsByClassName("container","span","aaa zzz").length);//1
}
正确的得到了结果。
原生的getElementsByClassName
有人会问,原生的方法调用效率是最高的,有很多浏览器已经将实现了getElementsByClassName这个方法,那为什这里没有先调用原生的再调用自定义的呢?
对,原生的效率是很高,它支持多个class条件的查询,但是最大的问题是他不支持getElementsByClassName("container","div","aaa ccc"),这种在指定标签中查找指定元素为指定class的情况。
所以,这里舍弃了原生的方法调用。
关于循环优化的问题
在代码中,你会看到我将数组的length缓存了起来,这样可以提高效率。其实上,在这里有一个很隐蔽的问题,就是数组访问length属性和HtmlCollection访问length有很在的区别。在数组中,length是一个普通的属性,访问时不会进行额外的操作,在来看看HTMLCollection,我们常常将HTMLCollection当作数组来使用,但实际上,它是一个根据DOM结构自动变化的实体对象。每次访问一个HTMLCollection对象的属性时,他都会对DOM内所有的节点进行一次完整的匹配。也就是说,每次访问HtmlCollection对象的length时,都会更新一次集合对象,性能上消耗很大。所以一般情况之下,这种HtmlCollection的循环操作,都是建议缓存length的。
额外的收获
这是关于往数组里放元素的方式间,效率比较的问题
来看一下代码:
复制代码 代码如下:
//方式一
var arr = [];
var start = new Date();
for(var i=0;i<100000;i++){
arr.push(i);
}
//方式二
var arr = [];
var start = new Date();
for(var i=0;i<100000;i++){
arr[arr.length]=i;
}
猜猜看,哪种效率更高呢!经过测试,第二种方式的效率要高于第一种。
提醒:
这个版本是不兼容IE5的,以下是我给出的解释:
1.当你从那千分之几的统计数据里,再去疯钱的IE5测试人员的点击和专业程序员对IE5的好奇心,估计就只剩IE5被焚烧后的灰烬了。
2.你要想信灰烬的利用价值趋于零
3.如果到现在还没能说服你,那我想说,你很专业!即然这样,那还有IE3,IE2,IE?FF1,NN4...,我想你应该一并实现了。
一些坦白:我也不怎么说服得了我自已,唉,还是给一个IE5的解决方案吧:
IE5并不支持getElementByTagName("*")的形式,所以在这里要处理一下:
var elements = (tagName==='*'&&node.all)?node.all:node.getElementsByTagName(tagName);
好了,不多说的,这个函数简单实用,代码上我也写了注释,看明白应该已经没有什么问题了
复制代码 代码如下:
/*
* 根据元素clsssName得到元素集合
* @param fatherId 父元素的ID,默认为document
* @tagName 子元素的标签名
* @className 用空格分开的className字符串
*/
function getElementsByClassName(fatherId,tagName,className){
node = fatherId&&document.getElementById(fatherId) || document;
tagName = tagName || "*";
className = className.split(" ");
var classNameLength = className.length;
for(var i=0,j=classNameLength;i<j;i++){
//创建匹配类名的正则
className[i]= new RegExp("(^|\\s)" + className[i].replace(/\-/g, "\\-") + "(\\s|$)");
}
var elements = node.getElementsByTagName(tagName);
var result = [];
for(var i=0,j=elements.length,k=0;i<j;i++){//缓存length属性
var element = elements[i];
while(className[k++].test(element.className)){//优化循环
if(k === classNameLength){
result[result.length] = element;
break;
}
}
k = 0;
}
return result;
}
好,我们来测试一下:
复制代码 代码如下:
<div id="container">
<span class="aaa zzz ccc"></span>
<div class="aaa bbb ccc"></div>
</div>
<div class="aaa bbb ccc"></div>
复制代码 代码如下:
window.onload = function(){
alert(getElementsByClassName(document,"div","aaa ccc").length);//2
alert(getElementsByClassName("container","div","aaa ccc").length);//1
alert(getElementsByClassName("container","span","aaa zzz").length);//1
}
正确的得到了结果。
原生的getElementsByClassName
有人会问,原生的方法调用效率是最高的,有很多浏览器已经将实现了getElementsByClassName这个方法,那为什这里没有先调用原生的再调用自定义的呢?
对,原生的效率是很高,它支持多个class条件的查询,但是最大的问题是他不支持getElementsByClassName("container","div","aaa ccc"),这种在指定标签中查找指定元素为指定class的情况。
所以,这里舍弃了原生的方法调用。
关于循环优化的问题
在代码中,你会看到我将数组的length缓存了起来,这样可以提高效率。其实上,在这里有一个很隐蔽的问题,就是数组访问length属性和HtmlCollection访问length有很在的区别。在数组中,length是一个普通的属性,访问时不会进行额外的操作,在来看看HTMLCollection,我们常常将HTMLCollection当作数组来使用,但实际上,它是一个根据DOM结构自动变化的实体对象。每次访问一个HTMLCollection对象的属性时,他都会对DOM内所有的节点进行一次完整的匹配。也就是说,每次访问HtmlCollection对象的length时,都会更新一次集合对象,性能上消耗很大。所以一般情况之下,这种HtmlCollection的循环操作,都是建议缓存length的。
额外的收获
这是关于往数组里放元素的方式间,效率比较的问题
来看一下代码:
复制代码 代码如下:
//方式一
var arr = [];
var start = new Date();
for(var i=0;i<100000;i++){
arr.push(i);
}
//方式二
var arr = [];
var start = new Date();
for(var i=0;i<100000;i++){
arr[arr.length]=i;
}
猜猜看,哪种效率更高呢!经过测试,第二种方式的效率要高于第一种。
提醒:
这个版本是不兼容IE5的,以下是我给出的解释:
1.当你从那千分之几的统计数据里,再去疯钱的IE5测试人员的点击和专业程序员对IE5的好奇心,估计就只剩IE5被焚烧后的灰烬了。
2.你要想信灰烬的利用价值趋于零
3.如果到现在还没能说服你,那我想说,你很专业!即然这样,那还有IE3,IE2,IE?FF1,NN4...,我想你应该一并实现了。
一些坦白:我也不怎么说服得了我自已,唉,还是给一个IE5的解决方案吧:
IE5并不支持getElementByTagName("*")的形式,所以在这里要处理一下:
var elements = (tagName==='*'&&node.all)?node.all:node.getElementsByTagName(tagName);
好了,不多说的,这个函数简单实用,代码上我也写了注释,看明白应该已经没有什么问题了
富贵资源网 Design By www.hznty.com
广告合作:本站广告合作请联系QQ:858582 申请时备注:广告合作(否则不回)
免责声明:本站资源来自互联网收集,仅供用于学习和交流,请遵循相关法律法规,本站一切资源不代表本站立场,如有侵权、后门、不妥请联系本站删除!
免责声明:本站资源来自互联网收集,仅供用于学习和交流,请遵循相关法律法规,本站一切资源不代表本站立场,如有侵权、后门、不妥请联系本站删除!
富贵资源网 Design By www.hznty.com
暂无评论...
《魔兽世界》大逃杀!60人新游玩模式《强袭风暴》3月21日上线
暴雪近日发布了《魔兽世界》10.2.6 更新内容,新游玩模式《强袭风暴》即将于3月21 日在亚服上线,届时玩家将前往阿拉希高地展开一场 60 人大逃杀对战。
艾泽拉斯的冒险者已经征服了艾泽拉斯的大地及遥远的彼岸。他们在对抗世界上最致命的敌人时展现出过人的手腕,并且成功阻止终结宇宙等级的威胁。当他们在为即将于《魔兽世界》资料片《地心之战》中来袭的萨拉塔斯势力做战斗准备时,他们还需要在熟悉的阿拉希高地面对一个全新的敌人──那就是彼此。在《巨龙崛起》10.2.6 更新的《强袭风暴》中,玩家将会进入一个全新的海盗主题大逃杀式限时活动,其中包含极高的风险和史诗级的奖励。
《强袭风暴》不是普通的战场,作为一个独立于主游戏之外的活动,玩家可以用大逃杀的风格来体验《魔兽世界》,不分职业、不分装备(除了你在赛局中捡到的),光是技巧和战略的强弱之分就能决定出谁才是能坚持到最后的赢家。本次活动将会开放单人和双人模式,玩家在加入海盗主题的预赛大厅区域前,可以从强袭风暴角色画面新增好友。游玩游戏将可以累计名望轨迹,《巨龙崛起》和《魔兽世界:巫妖王之怒 经典版》的玩家都可以获得奖励。