欢迎各位兄弟 发布技术文章

这里的技术是共享的

You are here

js 根据class 类名 返回所有对象

shiping1 的头像
  DOM 提供了一个名为 getElementById() 的方法,这个方法将返回一个对象,
这个对象就是参数 id 所对应的元素节点。另外,getElementByTagName()
方法会返回一个对象的数组,每一个对象分别对应着文档里有给定标签的一个元素。
这个方法的参数是 html 标签的名字。现在我们考虑一个问题,能不能通过标签的类名
class name来获取该对象呢?
下面是这个猜想的程序实现(支持多个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;
}

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

<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
}
普通分类: