js中getByClass()函数
js中getByClass()函数进化史
对于js来说,我想每一个刚接触它的人都应该会抱怨:为什么没有一个通过class来获取元素的方法。尽管现在高版本的浏览器已经支持getElementsByClassName()方法,但是对于低版本浏览器来说,还是无法兼容,在脱离其他库的时候,还是得自己封装一个方法。
也可到独立博客查看:getByClass()函数进化史
下面列举几种网上常见的方法并说明存在的一些问题。
方法一

function getByClass1(oParent, sClass){
var aRes = []; //存放匹配结果的数组
var aEle = oParent.getElementsByTagName('*');
for(var i = 0; i < aEle.length; i++){
if(aEle[i].className == sClass){
aRes.push(aEle[i]);
}
}
return aRes;
}

当然class里的值只有一个时,上面的方法没问题,但当值为多个时,就会出现问题。
<div class="test"></div>
<div class="test box"></div>
<script>
getByClass1(document, 'test'); //只获取到第一个div
</script>
方法二
出现问题的时候,我们会尝试着改进,对于多类名的情况我们可以用正则去匹配是否包含所要查找的class名,于是就出现了下面这种写法:

function getByClass2(oParent, sClass){
var aRes = [];
var re = new RegExp('\\b' + sClass + '\\b', 'i'); //匹配sClass是一个独立的单词
var aEle = oParent.getElementsByTagName('*');
for(var i = 0; i < aEle.length; i++){
if(re.test(aEle[i].className)){
aRes.push(aEle[i]);
}
}
return aRes;
}

这种方法看似可以,解决了getByClass1()的问题,我也用了好长一段时间,但是还会有一个隐藏的bug。看下面的例子:

<div class="test"></div>
<div class="test_box"></div>
<div class="test-box"></div>
<script>
getByClass2(document, 'test'); //结果获取到了第一个div和第三个div
</script>

理论上应该只获取到第一个,但是却和我们预期不一样。这个bug源于下面这段代码里的\b
var re = new RegExp('\\b' + sClass + '\\b', 'i');
我们先来看下\b在正则中的表示的意思
\b是正则表达式规定的一个特殊代码,代表着单词的开头或结尾,也就是单词的分界处。
通俗点说:\b就是匹配一个单词(从左边界到右边界)。
而问题也就出在这里,\b把除字母、数字、下划线外的其他字符都当成是边界,对于上面的例子中第三个class值为test-box,\b匹配时,把连字符(-)当作单词边界,所以也匹配了第三个div。
方法三
因此我们还需要对上面方法进行进一步改进,这里参考了stackoverflow上提到的一种方法:
改进后的代码如下:

function getByClass3(oParent, sClass){
var aRes = [];
var re = new RegExp(' ' + sClass + ' ', 'i'); //匹配sClass时,两边需要有空格
var aEle = oParent.getElementsByTagName('*');
for(var i = 0; i < aEle.length; i++){
if(re.test(' ' + aEle[i].className + ' ')){
aRes.push(aEle[i]);
}
}
return aRes;
}

这种方法舍去了用\b而采用空格来匹配边界,先在获取到的className值两边加上空格,这样就保证了className里的每个值两边都会有空格,然后再用正则去匹配。
用这种方法暂时还未发现问题,但是使用时,方法中的单引号内的空格一定不能落下。
方法四
根据@冰麟轻武 的提示继续改进:

function getByClass3(oParent, sClass){
var aRes = [];
var re = new RegExp('(^|\\s)' + sClass + '($|\\s)', 'i');
var aEle = oParent.getElementsByTagName('*');
for(var i = 0; i < aEle.length; i++){
if(re.test(aEle[i].className)){
aRes.push(aEle[i]);
}
}
return aRes;
}

空格完全用正则来处理,这样省去了空格容易落下的问题,代码也更美观精简。
那么这种方法是否就是比较完美的呢,其实不然,下面来看下更优的方案。
方法五(完美版)
文章开头已经提到,高版本的浏览器已经支持getElementsByClassName()方法。出于性能考虑,对支持的浏览器使用原生方法势必会更好。而对于低版本的浏览器使用上面的方法四。

function getByClass(oParent, sClass){
if(oParent.getElementsByClassName){
return oParent.getElementsByClassName(sClass);
}else{
var aRes = [];
var re = new RegExp('(^|\\s)' + sClass + '($|\\s)', 'i');
var aEle = oParent.getElementsByTagName('*');
for(var i = 0; i < aEle.length; i++){
if(re.test(aEle[i].className)){
aRes.push(aEle[i]);
}
}
return aRes;
}
}

当然方法五自认为是相对较好的方案,如果有更优秀的方法欢迎留言补充。
js中getByClass()函数的更多相关文章
- JS中的函数,Array对象,for-in语句,with语句,自定义对象,Prototype
一)函数 A)JS中的函数的定义格式: function add(a,b) { var sum = a+b; document.write("两个数的和是:" + sum); // ...
- js中的函数,Date对象,Math对象和数组对象
函数就是完成某个功能的一组语句,js中的函数由关键字 function + 函数名 + 一组参数定义;函数在定义后可以被重复调用,通常将常用的功能写成一个函数,利用函数可以使代码的组织结构更多清晰. ...
- JS中的函数、Bom、DOM及JS事件
本期博主给大家带来JS的函数.Bom.DOM操作,以及JS各种常用的数据类型的相关知识,同时,这也是JavaScript极其重要的部分,博主将详细介绍各种属性的用法和方法. 一.JS中的函数 [函数的 ...
- node.js 中回调函数callback(转载),说的很清楚,看一遍就理解了
最近在看 express,满眼看去,到处是以函数作为参数的回调函数的使用.如果这个概念理解不了,nodejs.express 的代码就会看得一塌糊涂.比如: 复制代码 代码如下: app.use(fu ...
- JS中的函数、BOM和DOM操作
一.JS中的函数 [关于注释] /** [文档注释]:开头两个*.写在函数上方,在调用函数时可以看到文档上方的描述信息. */ // 单行注释 /* 多行注释 */ 1.函数的声明及调用 (1) ...
- html css <input> javaScript .数据类型 JS中的函数编写方式 BOM总结 DOM总结
Day27 html css div 块标签. 特点: 独占一行,有高度和宽度 span 行元素. 特点:在同一行显示,当前行满了自动去下一行显示. 不识别高度和宽度 1.1.1.1 2.输入域标签 ...
- 前端之js中的函数
函数 函数就是重复执行的代码片. 函数定义与执行 <script type="text/javascript"> // 函数定义 function ...
- JS中的函数节流throttle详解和优化
JS中的函数节流throttle详解和优化在前端开发中,有时会为页面绑定resize事件,或者为一个页面元素绑定拖拽事件(mousemove),这种事件有一个特点,在一个正常的操作中,有可能在一个短的 ...
- JS中encodeURIComponent函数用php解码的代码
JS中encodeURIComponent函数给中文编码后,如何用php解码?? 前提:编码前的中文可能是gbk,gb2312,utf-8等. 复制代码 代码如下: urldecode() iconv ...
随机推荐
- 【百度地图API】让用户选择起点和终点的驾车导航
原文:[百度地图API]让用户选择起点和终点的驾车导航 摘要: 如果用户搜索“从机场到火车站”,使用驾车导航DrivingRoute会默认显示一条结果.但同一个城市可能有多个机场和火车站,那么,如何用 ...
- iOS_文章3党库SDWebImage
1,下载的文章3党库SDWebImage代码包增加到project 2,进入project的Build Phases,将源代码包里面的所有.m文件所有加入到project 3,导入第3方类库依赖的两个 ...
- Write the code.Change the world.---WWDC2014
- Java项目生成静态页面
第一次做项目需要生成静态页面,网上很多大牛对将网页生成静态页面有很多异议.说一下我的看法. 不外乎有以下因素: 1.从页面加载时间来看:静态页面不需要与数据库建立连接,尤其是访问数据量较大的页面,这种 ...
- 一步一步写算法(之n!中末尾零的个数统计)
原文:一步一步写算法(之n!中末尾零的个数统计) [ 声明:版权所有,欢迎转载,请勿用于商业用途. 联系信箱:feixiaoxing @163.com] 在很多面试的题目中,求n!结果中零的个数也是 ...
- PHP 调用asp.net Web Services服务问题总结
原文:PHP 调用asp.net Web Services服务问题总结 PHP是弱类型语言,转换非常不方便. < ?php //soap 客户端 $client=new SoapClient(' ...
- 使用 C# 进行 Outlook 2007 编程
原文:使用 C# 进行 Outlook 2007 编程 探讨如何使用 C# 编程语言生成 Outlook 识别的应用程序和 Outlook 外接程序. 请从"Add References&q ...
- C++中出现的计算机术语4
adaptor(适配器) 一种标准库类型.函数或迭代器,使某种标准库类型.函数或迭代器的行为类似于第二种标准库类型.函数或迭代器.系统提供了三种顺序容器适配器:stack(栈).queue(队列)以及 ...
- [译]Java 设计模式 之模板方法
(文章翻译自Java Design Pattern: Template Method) 模板方法设计模式定义了归档特定操作的工作流.它允许子类去修改特定的步奏而不用改变工作流的结构. 下面的例子表示模 ...
- leetcode第五题--Longest Palindromic Substring
Problem:Given a string S, find the longest palindromic substring in S. You may assume that the maxim ...