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 相关文章推荐
纯js实现背景图片切换效果代码
Nov 14 Javascript
JavaScript的document对象和window对象详解
Dec 30 Javascript
chrome原生方法之数组
Nov 30 Javascript
jQuery ui插件的使用方法代码实例
May 08 Javascript
JS实现的仿东京商城菜单、仿Win右键菜单及仿淘宝TAB特效合集
Sep 28 Javascript
详解JS面向对象编程
Jan 24 Javascript
prototype.js常用函数详解
Jun 18 Javascript
AngularJS动态绑定HTML的方法分析
Nov 07 Javascript
原生JS实现网页手机音乐播放器 歌词同步播放的示例
Feb 02 Javascript
vue+axios+promise实际开发用法详解
Oct 15 Javascript
详解Angular模板引用变量及其作用域
Nov 23 Javascript
javascript实现多边形碰撞检测
Oct 24 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
怎样在UNIX系统下安装MySQL
2006/10/09 PHP
ThinkPHP2.x防范XSS跨站攻击的方法
2015/09/25 PHP
PHP用FTP类上传文件视频等的简单实现方法
2016/09/23 PHP
Laravel 实现密码重置功能
2018/02/23 PHP
JSQL SQLProxy 的 php 版本代码
2010/05/05 Javascript
离开页面时检测表单元素是否被修改,提示保存的js代码
2010/08/25 Javascript
通过JS自动隐藏手机浏览器的地址栏实现原理与代码
2013/01/02 Javascript
js菜单点击显示或隐藏效果的简单实例
2014/01/13 Javascript
Jquery原生态实现表格header头随滚动条滚动而滚动
2014/03/18 Javascript
JS动态修改iframe高度和宽度的方法
2015/04/01 Javascript
实现音乐播放器的代码(html5+css3+jquery)
2015/08/04 Javascript
js实现的奥运倒计时时钟效果代码
2015/12/09 Javascript
jQuery实现右下角可缩放大小的层完整实例
2016/06/20 Javascript
浅谈js数据类型判断与数组判断
2016/08/29 Javascript
javascript实现无法关闭的弹框
2016/11/27 Javascript
详解VScode编辑器vue环境搭建所遇问题解决方案
2019/04/26 Javascript
小程序click-scroll组件设计
2019/06/18 Javascript
Vue如何循环提取对象数组中的值
2020/11/18 Vue.js
[03:39]DOTA2英雄梦之声_第05期_幽鬼
2014/06/23 DOTA
合并Excel工作薄中成绩表的VBA代码,非常适合教育一线的朋友
2009/04/09 Python
Python中的两个内置模块介绍
2015/04/05 Python
详解Python如何生成词云的方法
2018/06/01 Python
pycharm运行出现ImportError:No module named的解决方法
2018/10/13 Python
Python定时发送消息的脚本:每天跟你女朋友说晚安
2018/10/21 Python
Python3实现计算两个数组的交集算法示例
2019/04/03 Python
pytorch自定义二值化网络层方式
2020/01/07 Python
python之生成多层json结构的实现
2020/02/27 Python
如何利用Python写个坦克大战
2020/11/18 Python
开办加工厂创业计划书
2014/01/03 职场文书
学徒工职责
2014/03/06 职场文书
电子商务专业毕业生求职信
2014/06/12 职场文书
打架检讨书
2015/01/27 职场文书
师范生见习总结范文
2015/06/23 职场文书
《梅花魂》教学反思
2016/02/18 职场文书
小学语文课《掌声》教学反思
2016/03/03 职场文书
导游词之南京夫子庙
2019/12/09 职场文书