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 相关文章推荐
jQuery 1.2.x 升? 1.3.x 注意事项
May 06 Javascript
js 返回时间戳所对应的具体时间
Jul 20 Javascript
jquery的ajaxSubmit()异步上传图片并保存表单数据演示代码
Jun 04 Javascript
js行号显示的文本框实现效果(兼容多种浏览器 )
Oct 23 Javascript
JS实现双击屏幕滚动效果代码
Oct 28 Javascript
JavaScript编写检测用户所使用的浏览器的代码示例
May 05 Javascript
微信小程序入门教程
Nov 18 Javascript
JavaScript仿微信打飞机游戏
Jul 05 Javascript
详解webpack自动生成html页面
Jun 29 Javascript
微信小程序开发之animation循环动画实现的让云朵飘效果
Jul 14 Javascript
打通前后端构建一个Vue+Express的开发环境
Jul 17 Javascript
vue中beforeRouteLeave实现页面回退不刷新的示例代码
Nov 01 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安全性漫谈
2012/06/28 PHP
php计算整个目录大小的方法
2015/06/01 PHP
Yii中创建自己的Widget实例
2016/01/05 PHP
PHP基于反射机制实现插件的可插拔设计详解
2016/11/10 PHP
Laravel 解决composer相关操作提示php相关异常的问题
2019/10/23 PHP
javascript里的条件判断
2007/02/27 Javascript
checkbox 复选框不能为空
2009/07/11 Javascript
jQuery 动画弹出窗体支持多种展现方式
2010/04/29 Javascript
JavaScript prototype属性使用说明
2010/05/13 Javascript
jQuery效果 slideToggle() 方法(在隐藏和显示之间切换)
2011/06/28 Javascript
js innerHTML 改变div内容的方法
2013/08/03 Javascript
jQuery遍历json中多个map的方法
2015/02/12 Javascript
javascript实现网页子页面遍历回调的方法(涉及 window.frames、递归函数、函数上下文)
2015/07/27 Javascript
JavaScript采用递归算法计算阶乘实例
2015/08/04 Javascript
BootStrap下jQuery自动完成的样式调整
2016/05/30 Javascript
JavaScript中定义对象原型的两种使用方法
2016/12/15 Javascript
Node.js数据库操作之连接MySQL数据库(一)
2017/03/04 Javascript
微信小程序之数据缓存的实例详解
2017/09/29 Javascript
Js利用prototype自定义数组方法示例
2017/10/20 Javascript
three.js中文文档学习之通过模块导入
2017/11/20 Javascript
vue组件中使用iframe元素的示例代码
2017/12/13 Javascript
详解VUE里子组件如何获取父组件动态变化的值
2018/12/26 Javascript
JS回调函数原理与用法详解【附PHP回调函数】
2019/07/20 Javascript
vue+element-ui+axios实现图片上传
2019/08/20 Javascript
Python单元测试unittest的具体使用示例
2018/12/17 Python
django项目用higcharts统计最近七天文章点击量
2019/08/17 Python
详解python tcp编程
2020/08/24 Python
爬虫代理的cookie如何生成运行
2020/09/22 Python
香蕉共和国Banana Republic官网:美国GAP旗下偏贵族风格服饰品牌
2016/11/21 全球购物
美国汽配连锁巨头Pep Boys官网:轮胎更换、汽车维修服务和汽车零部件
2017/01/14 全球购物
雅高酒店中国:Accorhotels.com China
2018/03/26 全球购物
医科大学生的自我评价
2013/12/04 职场文书
公司前台辞职报告
2014/01/19 职场文书
幼儿园端午节活动总结
2015/05/05 职场文书
nginx负载功能+nfs服务器功能解析
2022/02/28 Servers
Python可视化神器pyecharts之绘制箱形图
2022/07/07 Python