getElementsByClassName的实现

首先我们看jquery作者的一篇getElementsByClassName Speed Comparison

有三种实现

1 纯DOM:通过getElementsByClassName("*")来遍历所有的dom元素,然后用正则判断className

2 DOM TreeWalker:dom2实现

3 XPath:通过XPath引擎来实现遍历

dom TreeWalker。通过使用dom level 2实现。

 
  
document.getElementsByClass = function (needle) {
function acceptNode(node) {
if (node.hasAttribute( " class " )) {
var c = " " + node.className + " " ;
if (c.indexOf( " " + needle + " " ) != - 1 )
return NodeFilter.FILTER_ACCEPT;
}
return NodeFilter.FILTER_SKIP;
}
var treeWalker = document.createTreeWalker(document.documentElement,
NodeFilter.SHOW_ELEMENT, acceptNode,
true );
var outArray = new Array();
if (treeWalker) {
var node = treeWalker.nextNode();
while (node) {
outArray.push(node);
node
= treeWalker.nextNode();
}
}
return outArray;
}

ulitimate  getElementsByClassName

使用纯dom实现,对ie实现了一些优化

 
  
function getElementsByClassName(oElm, strTagName, strClassName){
var arrElements = (strTagName == " * " && oElm.all) ? oElm.all :
oElm.getElementsByTagName(strTagName);
var arrReturnElements = new Array();
strClassName
= strClassName.replace( / \- / g, " \\- " );
var oRegExp = new RegExp( " (^|\\s) " + strClassName + " (\\s|$) " );
var oElement;
for ( var i = 0 ; i < arrElements.length; i ++ ){
oElement
= arrElements[i];
if (oRegExp.test(oElement.className)){
arrReturnElements.push(oElement);
}
}
return (arrReturnElements)
}

Dustin Diaz's getElementsByClass
一个纯dom实现

 
  
function getElementsByClass(searchClass,node,tag) {
var classElements = new Array();
if ( node == null )
node
= document;
if ( tag == null )
tag
= ' * ' ;
var els = node.getElementsByTagName(tag);
var elsLen = els.length;
var pattern = new RegExp( " (^|\\s) " + searchClass + " (\\s|$) " );
for (i = 0 , j = 0 ; i < elsLen; i ++ ) {
if ( pattern.test(els[i].className) ) {
classElements[j]
= els[i];
j
++ ;
}
}
return classElements;
}

prototype1.5的XPath

 
  
document.getElementsByClassName = function (className, parentElement) {
if (Prototype.BrowserFeatures.XPath) {
var q = " .//*[contains(concat(' ', @class, ' '), ' " + className + " ')] " ;
return document._getElementsByXPath(q, parentElement);
}
else {
var children = ($(parentElement) || document.body).getElementsByTagName( ' * ' );
var elements = [], child;
for ( var i = 0 , length = children.length; i < length; i ++ ) {
child
= children[i];
if (Element.hasClassName(child, className))
elements.push(Element.extend(child));
}
return elements;
}
};

Native firfefox3用C++写的

document.getElementsByClassName

速度对照表

getElementsByClassName对比

下面我们写一个getElementsByClassName的实现

var getElementsByClassName = function (searchClass, node,tag) {
    var classes = searchClass.split(" "),returnElements = [];
    if(document.getElementsByClassName){
	for(var mm1=0;mm1<classes.length;mm1++)	
	for(var mm2=0;mm2<document.getElementsByClassName(classes[mm1]).length;mm2++)
      returnElements.push(document.getElementsByClassName(classes[mm1])[mm2]);
    }else{
        node = node || document;
        tag = tag || "*";
      var elements = (tag === "*" && node.all)? node.all : node.getElementsByTagName(tag),
        patterns = [],
        current,
        match;
        var i = classes.length;
        while(--i >= 0){
            patterns.push(new RegExp("(^|\\s)" + classes[i] + "(\\s|$)","i"));
        }
        var j = elements.length;
        while(--j >= 0){
            current = elements[j];
            match = false;
            for(var k=0, kl=patterns.length; k<kl; k++){
                match = patterns[k].test(current.className);
            }
          if (match)  returnElements.push(current);
        }
    }
	        return returnElements;
}

用法:getElementsByClassName("class1 class2")
参数:可接受多个class参数

返回:返回所有包含class1或者class2的元素

var getElementsByClassName = function (searchClass, node,tag) { var classes = searchClass.split(" "),returnElements = []; if(document.getElementsByClassName){ for(var mm1=0;mm1<classes.length;mm1++) for(var mm2=0;mm2<document.getElementsByClassName(classes[mm1]).length;mm2++) returnElements.push(document.getElementsByClassName(classes[mm1])[mm2]); }else{ node = node || document; tag = tag || "*"; var elements = (tag === "*" && node.all)? node.all : node.getElementsByTagName(tag), patterns = [], current, match; var i = classes.length; while(--i >= 0){ patterns.push(new RegExp("(^|\\s)" + classes[i] + "(\\s|$)","i")); } var j = elements.length; while(--j >= 0){ current = elements[j]; match = false; for(var k=0, kl=patterns.length; k<kl; k++){ match = patterns[k].test(current.className); } if (match) returnElements.push(current); } } return returnElements; } alert(getElementsByClassName("menu").length) 运行代码

转载于:https://www.cnblogs.com/lunalord/archive/2011/03/17/1987268.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值