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 相关文章推荐
使用prototype.js进行异步操作
Feb 07 Javascript
jquery.validate使用时遇到的问题
May 25 Javascript
判断是否存在子节点的实现代码
May 18 Javascript
JS集成fckeditor及判断内容是否为空的方法
May 27 Javascript
node.js路径处理方法以及绝对路径详解
Mar 04 Javascript
JavaScript实现页面无操作倒计时退出
Oct 22 Javascript
原生javascript上传图片带进度条【实例分享】
Apr 06 Javascript
JavaScript中document.referrer的用法详解
Jul 04 Javascript
基于js 本地存储(详解)
Aug 16 Javascript
jQuery中 DOM节点操作方法大全
Oct 12 jQuery
详解React 在服务端渲染的实现
Nov 16 Javascript
如何对react hooks进行单元测试的方法
Aug 14 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 之 没有mysql支持时的替代方案
2006/10/09 PHP
javascript,php获取函数参数对象的代码
2011/02/03 PHP
PHP全概率运算函数(优化版) Webgame开发必备
2011/07/04 PHP
php jq jquery getJSON跨域提交数据完整版
2013/09/13 PHP
神盾加密解密教程(二)PHP 神盾解密
2014/06/08 PHP
PHP两种去掉数组重复值的方法比较
2014/06/19 PHP
ThinkPHP实现ajax仿官网搜索功能实例
2014/12/02 PHP
php通过PHPExcel导入Excel表格到MySQL数据库的简单实例
2016/10/29 PHP
老鱼 浅谈javascript面向对象编程
2010/03/04 Javascript
Javascript实现CheckBox的全选与取消全选的代码
2010/07/20 Javascript
JavaScript实现的encode64加密算法实例分析
2015/04/15 Javascript
javascript实现状态栏文字首尾相接循环滚动的方法
2015/07/22 Javascript
js正则表达式验证邮件地址
2015/11/12 Javascript
谈一谈javascript闭包
2016/01/28 Javascript
原生js实现图片层叠轮播切换效果
2016/02/02 Javascript
JS实现的仿QQ空间图片弹出效果代码
2016/02/23 Javascript
文件上传的几个示例分享【推荐】
2016/12/16 Javascript
微信小程序 input输入框详解及简单实例
2017/01/10 Javascript
jQuery动态生成表格及右键菜单功能示例
2017/01/13 Javascript
vue使用drag与drop实现拖拽的示例代码
2017/09/07 Javascript
浅谈js闭包理解
2019/04/01 Javascript
[01:35]2014DOTA2西雅图邀请赛 专访狐狸妈青春献给刀塔
2014/07/08 DOTA
[50:27]Secret vs VG 2018国际邀请赛小组赛BO2 第二场 8.17
2018/08/20 DOTA
利用打码兔和超人打码自封装的打码类分享
2014/03/16 Python
在Python中编写数据库模块的教程
2015/04/29 Python
深入理解python try异常处理机制
2016/06/01 Python
取numpy数组的某几行某几列方法
2018/04/03 Python
解决pycharm无法识别本地site-packages的问题
2018/10/13 Python
python设计微型小说网站(基于Django+Bootstrap框架)
2019/07/08 Python
python中not、and和or的优先级与详细用法介绍
2020/11/03 Python
详解基于 Canvas 手撸一个六边形能力图
2019/09/02 HTML / CSS
维也纳通行证:Vienna PASS
2019/07/18 全球购物
信息管理与信息系统专业求职信
2014/06/21 职场文书
2015年房地产个人工作总结
2015/05/26 职场文书
超级实用的公文标题大全!
2019/07/19 职场文书
pytorch中的 .view()函数的用法介绍
2022/03/17 Python