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 相关文章推荐
web前端开发也需要日志
Dec 09 Javascript
推荐40个非常优秀的jQuery插件和教程【系列三】
Nov 09 Javascript
jQuery判断密码强度实现思路及代码
Apr 24 Javascript
jQuery图片滚动图片的效果(另类实现)
Jun 02 Javascript
jquery实现在光标位置插入内容的方法
Feb 05 Javascript
jQuery实现的登录浮动框效果代码
Sep 26 Javascript
jQuery手动点击实现图片轮播特效
Apr 20 Javascript
JavaScript  cookie 跨域访问之广告推广
Apr 20 Javascript
浅析JavaScript中命名空间namespace模式
Jun 22 Javascript
Angularjs通过指令监听ng-repeat渲染完成后执行脚本的方法
Dec 31 Javascript
vue中过滤器filter的讲解
Jan 21 Javascript
VUE实现强制渲染,强制更新
Oct 29 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下统计用户在线时间的一种尝试
2010/08/26 PHP
php实现水仙花数的4个示例分享
2014/04/08 PHP
PHP框架Laravel的小技巧两则
2015/02/10 PHP
php高性能日志系统 seaslog 的安装与使用方法分析
2020/02/29 PHP
JavaScript操作XML实例代码(获取新闻标题并分页,并分页)
2010/05/25 Javascript
JQuery Study Notes 学习笔记(一)
2010/08/04 Javascript
浏览器常用高宽的jquery插件
2011/02/24 Javascript
javascript一元操作符(递增、递减)使用示例
2013/08/07 Javascript
详细介绍8款超实用JavaScript框架
2013/10/25 Javascript
JS实现判断滚动条滚到页面底部并执行事件的方法
2014/12/18 Javascript
轻松实现JavaScript图片切换
2016/01/12 Javascript
Three.js获取鼠标点击的三维坐标示例代码
2017/03/24 Javascript
vue项目webpack中Npm传递参数配置不同域名接口
2018/06/15 Javascript
详解如何使用React Hooks请求数据并渲染
2020/10/18 Javascript
Python人脸识别初探
2017/12/21 Python
python实现简单聊天室功能 可以私聊
2019/07/12 Python
python监控nginx端口和进程状态
2019/09/06 Python
如何运行带参数的python脚本
2019/11/15 Python
在Python中用GDAL实现矢量对栅格的切割实例
2020/03/11 Python
pytorch 计算ConvTranspose1d输出特征大小方式
2020/06/23 Python
关于pycharm 切换 python3.9 报错 ‘HTMLParser‘ object has no attribute ‘unescape‘ 的问题
2020/11/24 Python
css3背景图片透明叠加属性cross-fade简介及用法实例
2013/01/08 HTML / CSS
在HTML5 canvas里用卷积核进行图像处理的方法
2018/05/02 HTML / CSS
香港化妆品经销商:我的公主
2016/08/05 全球购物
英国、欧洲和全球租车服务:Avis英国
2016/08/29 全球购物
俄罗斯品牌服装在线商店:VIPAVENUE
2020/08/10 全球购物
计算机科学与技术应届生求职信
2013/11/07 职场文书
世界读书日的活动方案
2014/08/20 职场文书
开发房地产协议书
2014/09/14 职场文书
元旦标语大全
2014/10/09 职场文书
2015元旦主持词开场白和结束语
2014/12/14 职场文书
商超业务员岗位职责
2015/02/13 职场文书
摘录式读书笔记
2015/07/01 职场文书
创业计划书之书店
2019/09/10 职场文书
《模拟人生4》推出新补丁 “婚礼奇缘”DLC终于得到修复
2022/04/03 其他游戏
Ruby GDBM操作简介及数据存储原理
2022/04/19 Ruby