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 相关文章推荐
xml分页+ajax请求数据源+dom取结果实例代码
Oct 31 Javascript
JS 判断代码全收集
Apr 28 Javascript
Javascript 作用域使用说明
Aug 13 Javascript
js 编写规范
Mar 03 Javascript
js编码之encodeURIComponent使用介绍(asp,php)
Mar 01 Javascript
JavaScript实现检查页面上的广告是否被AdBlock屏蔽了的方法
Nov 03 Javascript
JavaScript实现的双向跨域插件分享
Jan 31 Javascript
JavaScript设计模式之代理模式简单实例教程
Jul 03 Javascript
详解关于Vue2.0路由开启keep-alive时需要注意的地方
Sep 18 Javascript
对angularJs中controller控制器scope父子集作用域的实例讲解
Oct 08 Javascript
JavaScript实现图片伪异步上传过程解析
Apr 10 Javascript
JavaScript最完整的深浅拷贝实现方式详解
Feb 28 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/07/17 PHP
php 中英文语言转换类
2011/09/07 PHP
php引用地址改变变量值的问题
2012/03/23 PHP
jQuery中调用WebService方法小结
2011/03/28 Javascript
JS小功能(操作Table--动态添加删除表格及数据)实现代码
2013/11/28 Javascript
js 异步操作回调函数如何控制执行顺序
2013/12/24 Javascript
Firefox下无法正常显示年份的解决方法
2014/09/04 Javascript
JavaScript节点及列表操作实例小结
2015/08/05 Javascript
实例解析jQuery插件EasyUI最常用的表单验证规则
2015/11/29 Javascript
基于jquery实现页面滚动到底自动加载数据的功能
2015/12/19 Javascript
理解js回收机制通俗易懂版
2016/02/29 Javascript
Angularjs中使用Filters详解
2016/03/11 Javascript
基于chosen插件实现人员选择树搜索自动筛选功能
2016/09/24 Javascript
微信小程序 教程之注册程序
2016/10/17 Javascript
详解前端自动化工具gulp自动添加版本号
2016/12/20 Javascript
layui表格实现代码
2017/05/20 Javascript
微信小程序实现倒计时调用相机自动拍照功能
2018/06/10 Javascript
在Vue中使用icon 字体图标的方法
2019/06/14 Javascript
微信小程序实现禁止分享代码实例
2019/10/19 Javascript
Vuejs通过拖动改变元素宽度实现自适应
2020/09/02 Javascript
详解Python中的__new__、__init__、__call__三个特殊方法
2016/06/02 Python
解决python2.7 查询mysql时出现中文乱码
2016/10/09 Python
python3+PyQt5+Qt Designer实现扩展对话框
2018/04/20 Python
对python程序内存泄漏调试的记录
2018/06/11 Python
Python实现的微信支付方式总结【三种方式】
2019/04/13 Python
django项目用higcharts统计最近七天文章点击量
2019/08/17 Python
python自动结束mysql慢查询会话的实例代码
2019/10/27 Python
python GUI库图形界面开发之PyQt5切换按钮控件QPushButton详细使用方法与实例
2020/02/28 Python
python剪切视频与合并视频的实现
2020/03/03 Python
python按顺序重命名文件并分类转移到各个文件夹中的实现代码
2020/07/21 Python
python如何实现图片压缩
2020/09/11 Python
python 发送get请求接口详解
2020/11/17 Python
全球知名鞋履品牌授权零售商:Journeys
2016/09/17 全球购物
阳光体育活动方案
2014/02/16 职场文书
地下停车场租赁协议范本
2014/10/07 职场文书
导游词之蜀山胜景瓦屋山
2019/11/29 职场文书