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 相关文章推荐
javascript函数作用域学习示例(js作用域)
Jan 13 Javascript
jquery操作select大全
Apr 25 Javascript
javascript文本模板用法实例
Jul 31 Javascript
jQuery热气球动画半透明背景的后台登录界面代码分享
Aug 28 Javascript
vue.js入门(3)——详解组件通信
Dec 02 Javascript
浅谈angularjs $http提交数据探索
Jan 20 Javascript
JS实现简易的图片拖拽排序实例代码
Jun 09 Javascript
React Native基础入门之调试React Native应用的一小步
Jul 02 Javascript
echarts大屏字体自适应的方法步骤
Jul 12 Javascript
js动态获取时间的方法分析
Aug 02 Javascript
vue 实现微信浮标效果
Sep 01 Javascript
Vue看了就会的8个小技巧
Jan 21 Vue.js
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版快速排序、冒泡排序
2014/04/09 PHP
php向js函数传参的几种方法
2014/08/10 PHP
百万级别知乎用户数据抓取与分析之PHP开发
2015/09/28 PHP
在b/s开发中经常用到的javaScript技术
2006/08/23 Javascript
在JavaScript中获取请求的URL参数[正则]
2010/12/25 Javascript
详解Matlab中 sort 函数用法
2016/03/20 Javascript
最简单纯JavaScript实现Tab标签页切换的方式(推荐)
2016/07/25 Javascript
vue.js初学入门教程(2)
2016/11/07 Javascript
通过构造函数实例化对象的方法
2017/06/28 Javascript
基于jquery实现多选下拉列表
2017/08/02 jQuery
js截取字符串功能的实现方法
2017/09/27 Javascript
webpack-dev-server远程访问配置方法
2018/02/22 Javascript
Vue-路由导航菜单栏的高亮设置方法
2018/03/17 Javascript
关于vue编译版本引入的问题的解决
2018/09/17 Javascript
利用JavaScript缓存远程窃取Wi-Fi密码的思路详解
2018/11/05 Javascript
JavaScript显式数据类型转换详解
2019/03/18 Javascript
微信小程序与公众号卡券/会员打通的问题
2019/07/25 Javascript
基于mpvue的简单弹窗组件mptoast使用详解
2019/08/02 Javascript
layui监听select变化,以及设置radio选中的方法
2019/09/24 Javascript
vue element自定义表单验证请求后端接口验证
2019/12/11 Javascript
jquery实现简易验证插件封装
2020/09/13 jQuery
解决vue初始化项目一直停在downloading template的问题
2020/11/09 Javascript
微信小程序实现加入购物车滑动轨迹
2020/11/18 Javascript
python实现将元祖转换成数组的方法
2015/05/04 Python
简介Python的collections模块中defaultdict类型的用法
2016/07/07 Python
使用CSS实现弹性视频html5案例实践
2012/12/26 HTML / CSS
微软瑞士官方网站:Microsoft瑞士
2018/04/20 全球购物
Java基础面试题
2014/07/19 面试题
个人社会实践自我鉴定
2014/03/24 职场文书
《白鹅》教学反思
2014/04/13 职场文书
《音乐之都维也纳》教学反思
2014/04/16 职场文书
小学英语教师研修感悟
2015/11/18 职场文书
导游词之阳朔遇龙河
2019/12/16 职场文书
Python anaconda安装库命令详解
2021/10/16 Python
英镑符号 £
2022/02/17 杂记
世界十大评分最高的动漫,CLANNAD上榜,第八赚足人们眼泪
2022/03/18 日漫