getElementsByClassName实现

简介:

先来看一下代码:(支持多个class查询和在某个范围内进行查询)

01 /*
02  * 根据元素clsssName得到元素集合
03  * @param fatherId 父元素的ID,默认为document
04  * @tagName 子元素的标签名
05  * @className 用空格分开的className字符串
06  */
07 function getElementsByClassName(fatherId,tagName,className){
08     var node = fatherId&&document.getElementById(fatherId) || document;
09     tagName = tagName || "*";
10     className = className.split(" ");
11     var classNameLength = className.length;
12     for(var i=0,j=classNameLength;i<j;i++){
13         //创建匹配类名的正则
14         className[i]= new RegExp("(^|\\s)" + className[i].replace(/\-/g, "\\-") + "(\\s|$)");
15     }
16     var elements = node.getElementsByTagName(tagName);
17     var result = [];
18     for(var i=0,j=elements.length,k=0;i<j;i++){//缓存length属性
19         var element = elements[i];
20         while(className[k++].test(element.className)){//优化循环
21             if(k === classNameLength){
22                 result[result.length] = element;
23                 break;
24             }  
25         }
26         k = 0;
27     }
28     return result;
29 }

好,我们来测试一下:

1 <div id="container">
2     <span class="aaa zzz ccc"></span>
3     <div class="aaa bbb ccc"></div>
4 </div>
5 <div class="aaa bbb ccc"></div>
1 window.onload = function(){
2     alert(getElementsByClassName(document,"div","aaa ccc").length);//2
3     alert(getElementsByClassName("container","div","aaa ccc").length);//1
4     alert(getElementsByClassName("container","span","aaa zzz").length);//1
5 }

正确的得到了结果。

 

关于class属性

1.一个元素可以带有多个class属性值,它们通过空格分隔, 例:class='aa bb cc'。

2.class属性值是可以包含'-'这个字符的,如:class='a-b',特别强调是因为在正则表达式中'-'是一个特殊字符。

3.在javascript中通过的获取class属性值的方式为element.className。

 

原生的getElementsByClassName

有人会问,原生的方法调用效率是最高的,有很多浏览器已经将实现了getElementsByClassName这个方法,那为什这里没有先调用原生的再调用自定义的呢?

对,原生的效率是很高,它支持多个class条件的查询,但是最大的问题是他不支持getElementsByClassName("container","div","aaa ccc"),这种在指定标签中查找指定元素为指定class的情况。

所以,这里舍弃了原生的方法调用。

 

关于循环优化的问题

在代码中,你会看到我将数组的length缓存了起来,这样可以提高效率。其实上,在这里有一个很隐蔽的问题,就是数组访问length属性和HtmlCollection访问length有很在的区别。在数组中,length是一个普通的属性,访问时不会进行额外的操作,在来看看HTMLCollection,我们常常将HTMLCollection当作数组来使用,但实际上,它是一个根据DOM结构自动变化的实体对象。每次访问一个HTMLCollection对象的属性时,他都会对DOM内所有的节点进行一次完整的匹配。也就是说,每次访问HtmlCollection对象的length时,都会更新一次集合对象,性能上消耗很大。所以一般情况之下,这种HtmlCollection的循环操作,都是建议缓存length的。

 

 

额外的收获

 这是关于往数组里放元素的方式间,效率比较的问题

来看一下代码:

01 //方式一
02 var arr = [];
03 var start = new Date();
04 for(var i=0;i<100000;i++){
05     arr.push(i);
06 }
07  
08 //方式二
09 var arr = [];
10 var start = new Date();
11 for(var i=0;i<100000;i++){
12     arr[arr.length]=i;
13 }

猜猜看,哪种效率更高呢!经过测试,第二种方式的效率要高于第一种。

 

提醒:

这个版本是不兼容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);

好了,不多说的,这个函数简单实用,代码上我也写了注释,看明白应该已经没有什么问题了

本文转自艾伦 Aaron博客园博客,原文链接:http://www.cnblogs.com/aaronjs/archive/2011/09/05/2167530.html,如需转载请自行联系原作者


相关文章
|
算法 数据安全/隐私保护
对称密钥加密算法和公开密钥加密算法有什么区别
【4月更文挑战第19天】对称密钥和公开密钥加密算法各有特点:对称密钥加密速度快,适用于大量数据,但密钥管理困难;公开密钥加密安全性高,密钥管理方便,但速度慢,常用于数字签名和身份验证。两者在不同场景下有不同优势。
802 6
|
存储 IDE 区块链
《Solidity 简易速速上手小册》第3章:Solidity 语法基础(2024 最新版)
《Solidity 简易速速上手小册》第3章:Solidity 语法基础(2024 最新版)
465 2
|
算法 测试技术 数据库
性能测试 (performance measurement)
性能测试 (performance measurement) 是一种测试方法,用于评估系统、应用程序或算法在特定负载条件下的性能表现。性能测试可以测量系统的响应时间、吞吐量、并发用户数等指标,以评估系统在高负载情况下的稳定性和可靠性。通过性能测试,可以找出系统的瓶颈和潜在的优化点,从而提高系统的性能。
471 3
|
5月前
|
存储 应用服务中间件 nginx
在使用Nginx之后,如何在web应用中获取用户IP以及相关原理
但总的来说,通过理解网络通信的基础知识,了解http协议以及nginx的工作方式,我们已经能在大多数情况下准确地获取用户的真实IP地址了,在调试问题或者记录日志时会起到很大的帮助。
284 37
|
5月前
|
人工智能 缓存 搜索推荐
1688图片搜索API接口解析与 Python实战指南
1688图片搜索API接口支持通过上传图片搜索相似商品,适用于电商及商品推荐场景。用户上传图片后,经图像识别提取特征并生成关键词,调用接口返回包含商品ID、标题和价格的相似商品列表。该接口需提供图片URL或Base64编码数据,还可附加分页与筛选参数。示例代码展示Python调用方法,调试时建议使用沙箱环境测试稳定性,并优化性能与错误处理逻辑。
|
12月前
|
监控 网络协议 应用服务中间件
深入解析:如何确定网站使用的端口号
【10月更文挑战第21天】 在网络通信中,端口号是识别特定服务的关键。一个IP地址可以有多个端口,每个端口可能运行着不同的服务。当我们在浏览器地址栏输入一个网址时,实际上是通过特定的端口与服务器进行通信。本文将探讨如何确定一个网站使用的端口号,以及端口号在网络通信中的作用。
1040 4
|
SQL 存储 搜索推荐
SQL游标的原理与在数据库操作中的应用
SQL游标的原理与在数据库操作中的应用
|
程序员
程序员必知:原码、反码、补码和移码详解
程序员必知:原码、反码、补码和移码详解
890 0
|
域名解析 网络协议 搜索推荐
阿里云DNS常见问题之获取不到用户真实IP地址如何解决
阿里云DNS(Domain Name System)服务是一个高可用和可扩展的云端DNS服务,用于将域名转换为IP地址,从而让用户能够通过域名访问云端资源。以下是一些关于阿里云DNS服务的常见问题合集:
|
安全 算法 编译器
【C++ 泛型编程 进阶篇】全面入门指南:深度探索C++ 元模板 std::declval的使用和应用
【C++ 泛型编程 进阶篇】全面入门指南:深度探索C++ 元模板 std::declval的使用和应用
408 0