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处理DOM元素事件实现代码
May 23 Javascript
js原型链原理看图说明
Jul 07 Javascript
javascript实现页面刷新时自动清空表单并选中的方法
Jul 18 Javascript
jQuery插入节点和移动节点用法示例(insertAfter、insertBefore方法)
Sep 08 Javascript
js中Number数字数值运算后值不对的解决方法
Feb 28 Javascript
基于JQuery和原生JavaScript实现网页定位导航特效
Apr 03 jQuery
vue vue-Router默认hash模式修改为history需要做的修改详解
Sep 13 Javascript
Vue中的作用域CSS和CSS模块的区别
Oct 09 Javascript
小程序绑定用户方案优化小结
May 15 Javascript
关于vue3默认把所有onSomething当作v-on事件绑定的思考
May 15 Javascript
JS 逻辑判断不要只知道用 if-else 和 switch条件判断(小技巧)
May 27 Javascript
Vue如何清空对象
Mar 03 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实现生成透明背景的PNG缩略图函数分享
2014/07/08 PHP
Yii框架结合sphinx,Ajax实现搜索分页功能示例
2016/10/18 PHP
PHP快速推送微信模板消息
2017/04/14 PHP
PHP编程获取音频文件时长的方法【基于getid3类】
2017/04/20 PHP
Domino中运用jQuery读取视图内容的方法
2009/10/21 Javascript
13 个JavaScript 性能提升技巧分享
2012/07/26 Javascript
JavaScript 语言基础知识点总结(思维导图)
2013/11/10 Javascript
IE浏览器不支持getElementsByClassName的解决方法
2014/08/27 Javascript
用js传递value默认值的示例代码
2014/09/11 Javascript
jQuery给多个不同元素添加class样式的方法
2015/03/26 Javascript
Js的Array数组对象详解
2016/02/22 Javascript
JS获取屏幕高度的简单实现代码
2016/05/24 Javascript
详解vue组件化开发-vuex状态管理库
2017/04/10 Javascript
webpack多入口文件页面打包配置详解
2018/01/09 Javascript
vue组件挂载到全局方法的示例代码
2018/08/02 Javascript
webpack4 SCSS提取和懒加载的示例
2018/09/03 Javascript
微信小程序冒泡事件及其阻止方法实例分析
2018/12/06 Javascript
微信小程序五子棋游戏AI实现方法【附demo源码下载】
2019/02/20 Javascript
解决微信浏览器缓存站点入口文件(IIS部署Vue项目)
2019/06/17 Javascript
通过js随机函数Math.random实现乱序
2020/05/19 Javascript
vue实现数字滚动效果
2020/06/29 Javascript
python实现监控windows服务并自动启动服务示例
2014/04/17 Python
跟老齐学Python之玩转字符串(2)
2014/09/14 Python
python类继承与子类实例初始化用法分析
2015/04/17 Python
利用Python命令行传递实例化对象的方法
2016/11/02 Python
python3 深浅copy对比详解
2019/08/12 Python
Django模板之基本的 for 循环 和 List内容的显示方式
2020/03/31 Python
html5 canvas合成海报所遇问题及解决方案总结
2017/08/03 HTML / CSS
SIXPAD智能健身仪英国官网:革命性的训练装备品牌
2018/09/27 全球购物
时尚孕妇装:Ingrid & Isabel
2019/05/08 全球购物
美国婴儿和儿童服装购物网站:PatPat
2020/10/01 全球购物
文秘专业应届生求职信范文
2013/11/14 职场文书
往来会计岗位职责
2013/12/19 职场文书
禁止酒驾标语
2014/06/25 职场文书
加入学生会自荐书
2015/03/05 职场文书
Node.js实现断点续传
2021/06/23 Javascript