javascript getElementsByClassName实现代码


Posted in Javascript onOctober 11, 2010

先来看一下代码:(支持多个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);
好了,不多说的,这个函数简单实用,代码上我也写了注释,看明白应该已经没有什么问题了
Javascript 相关文章推荐
syntaxhighlighter 使用方法
Jul 02 Javascript
javascript URL编码和解码使用说明
Apr 12 Javascript
基于JQuery的一句话搞定手风琴菜单
Sep 14 Javascript
document.documentElement的一些使用技巧
Apr 18 Javascript
jquery实现未经美化的简洁TAB菜单效果
Aug 28 Javascript
js实现的页面矩阵图形变换特效
Jan 26 Javascript
浅谈js中的三种继承方式及其优缺点
Aug 10 Javascript
Javascript基础回顾之(二) js作用域
Jan 31 Javascript
Angular中$broadcast和$emit的使用方法详解
May 22 Javascript
js通过Date对象实现倒计时动画效果
Oct 27 Javascript
Vue安装浏览器开发工具的步骤详解
May 12 Javascript
webpack5 联邦模块介绍详解
Jul 08 Javascript
javascript Array.prototype.slice使用说明
Oct 11 #Javascript
javascript 伪数组实现方法
Oct 11 #Javascript
javascript forEach通用循环遍历方法
Oct 11 #Javascript
JavaScript 操作键盘的Enter事件(键盘任何事件),兼容多浏览器
Oct 11 #Javascript
JavaScript isArray()函数判断对象类型的种种方法
Oct 11 #Javascript
JSChart轻量级图形报表工具(内置函数中文参考)
Oct 11 #Javascript
jQuery 表单验证扩展代码(一)
Oct 11 #Javascript
You might like
《PHP编程最快明白》第七讲:php图片验证码与缩略图
2010/11/01 PHP
用PHP即时捕捉PHP中的错误并发送email通知的实现代码
2013/01/19 PHP
Yii rules常用规则示例
2016/03/15 PHP
php版微信小店调用api示例代码
2016/11/12 PHP
Javascript中暂停功能的实现代码
2007/03/04 Javascript
javascript得到XML某节点的子节点个数的脚本
2008/10/11 Javascript
js制作的鼠标悬浮时产生的下拉框效果
2012/10/27 Javascript
jQuery实现仿QQ空间装扮预览图片的鼠标提示效果代码
2015/10/30 Javascript
JavaScript中windows.open()、windows.close()方法详解
2016/07/28 Javascript
React Native实现简单的登录功能(推荐)
2016/09/19 Javascript
微信小程序 less文件编译成wxss文件实现办法
2016/12/05 Javascript
JS 调试中常见的报错问题解决方法
2017/05/20 Javascript
详解vue 数据传递的方法
2018/04/19 Javascript
vue使用laydate时间插件的方法
2018/11/14 Javascript
ES6中的class是如何实现的(附Babel编译的ES5代码详解)
2019/05/17 Javascript
深入了解query和params的使用区别
2019/06/24 Javascript
js实现无限瀑布流实例方法
2019/09/16 Javascript
如何基于JS截获动态代码
2019/12/25 Javascript
vue+element实现动态加载表单
2020/12/13 Vue.js
Python函数式编程指南(三):迭代器详解
2015/06/24 Python
Python实现按照指定要求逆序输出一个数字的方法
2018/04/19 Python
对python中的pop函数和append函数详解
2018/05/04 Python
django manage.py扩展自定义命令方法
2018/05/27 Python
Python判断中文字符串是否相等的实例
2018/07/06 Python
pygame游戏之旅 游戏中添加显示文字
2018/11/20 Python
深入解析python中的实例方法、类方法和静态方法
2019/03/11 Python
python3实现飞机大战
2020/11/29 Python
索尼巴西商店:Sony巴西
2019/06/21 全球购物
酒店工作职员求职简历的自我评价
2013/10/23 职场文书
会计自我鉴定
2014/02/04 职场文书
超市中秋节促销方案
2014/03/21 职场文书
小学生竞选班长演讲稿
2014/04/24 职场文书
化工专业求职信
2014/07/01 职场文书
爱护公共设施演讲稿
2014/09/13 职场文书
毕业生实习期转正自我鉴定
2014/09/26 职场文书
个园导游词
2015/02/04 职场文书